mysql事务隔离级别测试
隔离性
mysql提供了4种不同的隔离级别以支持多版本并发控制(MVCC)
较低级别的隔离通常可以执行更高的并发,系统的开销也更低
read uncommited(未提交读)
read commited(提交读)
repeatable read(可重复读)
serializable(可串行化)
默认repeatable-read
建议最好不要修改默认的隔离级别,修改隔离级别会对mysql复制产生影响
isolation-table.sql
DROP TABLE IF EXISTS transaction_test;
CREATE TABLE transaction_test(
id INT UNSIGNED NOT NULL AUTO_INCREMENT,
val VARCHAR(20) NOT NULL,
created TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY(id)
) ENGINE=InnoDB DEFAULT CHARSET latin1; #初始化数据
insert into transaction_test(val) values ('a'),('b'),('c');
1.REPEATABLE-READ(可重复读)
解决了脏读问题.该级别保证了在同一事物中多次读取同样的记录结果是一样的。但是在理论上,可重复读隔离级别还是无法解决另外一个幻读问题
所谓幻读,是指当某个事务在读取某个范围的记录时,另外一个事务又在该范围内插入了新的记录,当之前的事务再次读取该范围的记录时,会产生幻行
innodb和XtraDB存储引擎通过多版本并发控制(MVCC)解决幻读问题。
select @@global.tx_isolation,@@session.tx_isolation;
+-----------------------+------------------------+
| @@global.tx_isolation | @@session.tx_isolation |
+-----------------------+------------------------+
| READ-UNCOMMITTED | READ-UNCOMMITTED |
+-----------------------+------------------------+
set @@global.tx_isolation='REPEATABLE-READ';
mysql> select @@global.tx_isolation,@@session.tx_isolation;
+-----------------------+------------------------+
| @@global.tx_isolation | @@session.tx_isolation |
+-----------------------+------------------------+
| REPEATABLE-READ | REPEATABLE-READ |
+-----------------------+------------------------+
第一个会话窗口
start transaction;
select * from transaction_test;
select sleep(20);
insert into transaction_test (val) values (@@session.tx_isolation);
select * from transaction_test;
commit;
在第一个会话正在运行时在第二个会话窗口里运行
start transaction;
insert into transaction_test (val) values ('x'),('y'),('z');
select * from transaction_test;
commit;
均执行结束后
mysql> select * from transaction_test;
+----+-----------------+---------------------+
| id | val | created |
+----+-----------------+---------------------+
| 1 | a | 2017-01-08 20:38:06 |
| 2 | b | 2017-01-08 20:38:06 |
| 3 | c | 2017-01-08 20:38:06 |
| 4 | x | 2017-01-08 20:38:41 |
| 5 | y | 2017-01-08 20:38:41 |
| 6 | z | 2017-01-08 20:38:41 |
| 7 | REPEATABLE-READ | 2017-01-08 20:38:59 |
+----+-----------------+---------------------+
7 rows in set (0.00 sec)
可以看到在第二个会话中,添加了3个新行,并在第一个会话事务完成前提交了数据
会话1里的执行状态
mysql> start transaction;
Query OK, 0 rows affected (0.00 sec) mysql> select * from transaction_test;
+----+-----+---------------------+
| id | val | created |
+----+-----+---------------------+
| 1 | a | 2017-01-08 20:45:48 |
| 2 | b | 2017-01-08 20:45:48 |
| 3 | c | 2017-01-08 20:45:48 |
+----+-----+---------------------+
3 rows in set (0.00 sec) mysql> select sleep(20);
+-----------+
| sleep(20) |
+-----------+
| 0 |
+-----------+
1 row in set (20.00 sec) mysql> insert into transaction_test (val) values (@@session.tx_isolation);
Query OK, 1 row affected (0.00 sec) mysql> select * from transaction_test;
+----+-----------------+---------------------+
| id | val | created |
+----+-----------------+---------------------+
| 1 | a | 2017-01-08 20:45:48 |
| 2 | b | 2017-01-08 20:45:48 |
| 3 | c | 2017-01-08 20:45:48 |
| 7 | REPEATABLE-READ | 2017-01-08 20:47:16 |
+----+-----------------+---------------------+
4 rows in set (0.00 sec) mysql> commit;
Query OK, 0 rows affected (0.06 sec)
第一个会话事务不知道第二个会话事务已完成的结果,整个事务过程中多次读取的数据是一致的(无论外表是否发生改变)
但会阻塞 truncate 操作,delete ,insert,
事务里做的修改(update,delete)未提交 会将这些数据锁定,阻塞其它的操作
2.READ-COMMITTED(读取提交内容)
TRUNCATE transaction_test;
insert into transaction_test(val) values ('a'),('b'),('c');
set @@global.tx_isolation='READ-COMMITTED';
mysql> select @@global.tx_isolation,@@session.tx_isolation;
+-----------------------+------------------------+
| @@global.tx_isolation | @@session.tx_isolation |
+-----------------------+------------------------+
| READ-COMMITTED | READ-COMMITTED |
+-----------------------+------------------------+
在session1中运行
start transaction;
select * from transaction_test;
select sleep(20);
insert into transaction_test (val) values (@@session.tx_isolation);
select * from transaction_test;
commit;
同时在session2中运行
start transaction;
insert into transaction_test (val) values ('x'),('y'),('z');
select * from transaction_test;
commit;
session1的运行显示
mysql> start transaction;
Query OK, 0 rows affected (0.00 sec) mysql> select * from transaction_test;
+----+-----+---------------------+
| id | val | created |
+----+-----+---------------------+
| 1 | a | 2017-01-08 21:11:26 |
| 2 | b | 2017-01-08 21:11:26 |
| 3 | c | 2017-01-08 21:11:26 |
+----+-----+---------------------+
3 rows in set (0.00 sec) mysql> select sleep(20);
+-----------+
| sleep(20) |
+-----------+
| 0 |
+-----------+
1 row in set (20.00 sec) mysql> insert into transaction_test (val) values (@@session.tx_isolation);
Query OK, 1 row affected (0.01 sec) mysql> select * from transaction_test;
+----+----------------+---------------------+
| id | val | created |
+----+----------------+---------------------+
| 1 | a | 2017-01-08 21:11:26 |
| 2 | b | 2017-01-08 21:11:26 |
| 3 | c | 2017-01-08 21:11:26 |
| 4 | x | 2017-01-08 21:11:50 |
| 5 | y | 2017-01-08 21:11:50 |
| 6 | z | 2017-01-08 21:11:50 |
| 7 | READ-COMMITTED | 2017-01-08 21:12:02 |
+----+----------------+---------------------+
7 rows in set (0.00 sec) mysql> commit;
Query OK, 0 rows affected (0.07 sec)
可以看到,在session1事务期间,事务内的数据结果发生了改变,以反映一个已提交的事务
这仅仅是一个演示,可能应用程序永远不会需要在某个事务期间,多次选择相同的信息
作为隔离级别的默认值,REPEATABLE-READ是最广泛使用和测试的隔离级别,应当优先于READ-COMMITED使用
3.READ-UNCOMMITED(读取未提交内容)
事务中的修改,即使没有提交,对其它事务也都是可见的。事务可以读取未提交的数据,这也称为脏读。这个级别会导致很多问题,从性能上来说不会比其它级别好太多,但缺乏其它级别的很多好处!
set @@global.tx_isolation='READ-UNCOMMITED';
运行之前的测试语句
先执行会话1
在执行会话2 不提交事务
等会话1执行完再提交会话2的事务
会发现会话1读到了会话2未提交的事务
4.SERIALIZABLE(序列化,可串行化)
此种情况下,在共享模式下对表进行了有效锁定,这会迫使事务阻塞其它事务
按照之前的测试语句
对于第一个会话,输出效果相同 ,造成第二个会话中insert的延迟,该insert将会被阻塞,直到第一个会话完成
set @@global.tx_isolation='SERIALIZABLE';
会话1
mysql> start transaction;
Query OK, 0 rows affected (0.00 sec) mysql> select * from transaction_test;
+----+-----+---------------------+
| id | val | created |
+----+-----+---------------------+
| 1 | a | 2017-01-08 22:34:59 |
| 2 | b | 2017-01-08 22:34:59 |
| 3 | c | 2017-01-08 22:34:59 |
+----+-----+---------------------+
3 rows in set (0.00 sec) mysql> select sleep(20);
+-----------+
| sleep(20) |
+-----------+
| 0 |
+-----------+
1 row in set (20.00 sec) mysql> insert into transaction_test (val) values (@@session.tx_isolation);
Query OK, 1 row affected (0.00 sec) mysql> select * from transaction_test;
+----+--------------+---------------------+
| id | val | created |
+----+--------------+---------------------+
| 1 | a | 2017-01-08 22:34:59 |
| 2 | b | 2017-01-08 22:34:59 |
| 3 | c | 2017-01-08 22:34:59 |
| 7 | SERIALIZABLE | 2017-01-08 22:36:12 |
+----+--------------+---------------------+
4 rows in set (0.00 sec) mysql> commit;
Query OK, 0 rows affected (0.34 sec)
会话2
mysql> start transaction;
Query OK, 0 rows affected (0.00 sec) mysql> insert into transaction_test (val) values ('x'),('y'),('z');
Query OK, 3 rows affected (13.04 sec)
Records: 3 Duplicates: 0 Warnings: 0 mysql> select * from transaction_test;
+----+--------------+---------------------+
| id | val | created |
+----+--------------+---------------------+
| 1 | a | 2017-01-08 22:34:59 |
| 2 | b | 2017-01-08 22:34:59 |
| 3 | c | 2017-01-08 22:34:59 |
| 4 | x | 2017-01-08 22:35:59 |
| 5 | y | 2017-01-08 22:35:59 |
| 6 | z | 2017-01-08 22:35:59 |
| 7 | SERIALIZABLE | 2017-01-08 22:36:12 |
+----+--------------+---------------------+
7 rows in set (0.00 sec)
mysql> commit;
Query OK, 0 rows affected (0.39 sec)
值得注意的是
auto_increment 列的顺序
所显示的顺序是实际语句初始化的顺序,
因为auto_increment列的值是作为对该表保持的一个单独的内部全局变量值而进行管理的,在执行期间,可以在内部独占的互斥体内获得该值
它独立于隔离级别而发挥作用,与实际sql数据的serializable相反,即数据直到加锁事务完成insert操作后,才会释放第二个会话的锁定
|
隔离级别 |
脏读可能性 |
不可重复读可能性 |
幻读可能性 |
加锁读 |
|
read uncommited |
Yes |
Yes |
Yes |
No |
|
read commited |
No |
Yes |
Yes |
No |
|
repeatable read |
No |
No |
Yes |
No |
|
seralizable |
No |
No |
No |
Yes |
表的外键和级联
DROP TABLE IF EXISTS trans_parent;
CREATE TABLE trans_parent (
id INT UNSIGNED NOT NULL AUTO_INCREMENT,
val VARCHAR(10) NOT NULL,
PRIMARY KEY (id),
UNIQUE KEY (val)
) ENGINE=InnoDB DEFAULT CHARSET latin1; 外键约束
DROP TABLE IF EXISTS trans_child;
CREATE TABLE trans_child (
id INT UNSIGNED NOT NULL AUTO_INCREMENT,
parent_id INT UNSIGNED NOT NULL,
created TIMESTAMP NOT NULL,
PRIMARY KEY (id),
INDEX (parent_id),
FOREIGN KEY (parent_id) REFERENCES trans_parent(id)
) ENGINE=InnoDB DEFAULT CHARSET latin1;
看一张表的索引
show index from trans_child;
看一张表的外键
use INFORMATION_SCHEMA; select TABLE_NAME,COLUMN_NAME,CONSTRAINT_NAME,REFERENCED_TABLE_NAME,REFERENCED_COLUMN_NAME from KEY_COLUMN_USAGE where table_name = 'trans_child'; +-------------+-------------+--------------------+-----------------------+------------------------+
| TABLE_NAME | COLUMN_NAME | CONSTRAINT_NAME | REFERENCED_TABLE_NAME | REFERENCED_COLUMN_NAME |
+-------------+-------------+--------------------+-----------------------+------------------------+
| trans_child | id | PRIMARY | NULL | NULL |
| trans_child | parent_id | trans_child_ibfk_1 | trans_parent | id |
+-------------+-------------+--------------------+-----------------------+------------------------+
如果删除trans_parent里的一条与trans_child有外键关联的表 会报错
级联约束
alter table trans_child
drop foreign key trans_child_ibfk_1,
add foreign key (parent_id) references trans_parent(id) on delete cascade; delete from trans_parent where id=1;//trans_child表里parent_id=1的纪录也会被删除
mysql事务隔离级别测试的更多相关文章
- MySQL事务隔离级别测试实例
https://www.cnblogs.com/huanongying/p/7021555.html MySQL事务隔离级别 事务隔离级别 脏读 不可重复读 幻读 读未提交(read-uncommit ...
- MySQL事务隔离级别(一)
本文实验的测试环境:Windows 10+cmd+MySQL5.6.36+InnoDB 一.事务的基本要素(ACID) 1.原子性(Atomicity):事务开始后所有操作,要么全部做完,要么全部不做 ...
- 面试突击61:说一下MySQL事务隔离级别?
MySQL 事务隔离级别是为了解决并发事务互相干扰的问题的,MySQL 事务隔离级别总共有以下 4 种: READ UNCOMMITTED:读未提交. READ COMMITTED:读已提交. REP ...
- [51CTO]新说MySQL事务隔离级别!
新说MySQL事务隔离级别! 事务隔离级别这个问题,无论是校招还是社招,面试官都爱问!然而目前网上很多文章,说句实在话啊,我看了后我都怀疑作者弄懂没!本文所讲大部分内容,皆有官网作为佐证,因此对本文内 ...
- 查询mysql事务隔离级别
查询mysql事务隔离级别 查询mysql事务隔离级别 分类: DB2011-11-26 13:12 2517人阅读 评论(0) 收藏 举报 mysqlsessionjava 1.查看当前会话隔离 ...
- Mysql事务-隔离级别
MYSQL事务-隔离级别 事务是什么? 事务简言之就是一组SQL执行要么全部成功,要么全部失败.MYSQL的事务在存储引擎层实现. 事务都有ACID特性: 原子性(Atomicity):一个事务必须被 ...
- MySQL事务隔离级别 解决并发问题
MySQL事务隔离级别 1. 脏读: 骗钱的手段, 两个窗口或线程分别调用数据库转账表,转账后未提交,对方查看到账后,rollback,实际钱没转. 演示方法: mysql默认的事务隔离级别为repe ...
- mysql事务隔离级别、脏读、幻读
Mysql事务隔离级别本身很重要,再加上可能是因为各大公司面试必问的缘故,在博客中出现的概率非常高,但不幸的是,中国的技术博客要么是转载,要么是照抄,质量参差不齐,好多结论都是错的,对于心怀好奇之心想 ...
- mysql事务隔离级别与设置
mysql数据库,当且仅当引擎是InnoDB,才支持事务: 1.隔离级别 事务的隔离级别分为:未提交读(read uncommitted).已提交读(read committed).可重复读(repe ...
随机推荐
- Newtonsoft.Json 序列 反序列 IEnumerable
下面是memcached 中获取的obj 类型的数据,转list string sessionId = Request.Cookies["sessionId"].Value;//授 ...
- Java解析XML的四种方法详解 - 转载
XML现在已经成为一种通用的数据交换格式,平台的无关性使得很多场合都需要用到XML.本文将详细介绍用Java解析XML的四种方法 在做一般的XML数据交换过程中,我更乐意传递XML字符串,而不是格式化 ...
- 落地案例|日本雅虎如何在 OpenStack 上大规模构建和运行 Kubernetes
今天的帖子是由日本雅虎的基础设施工程团队撰写,内容是他们如何在 Kubernetes 上运行 OpenStack.这篇帖子是由日本雅虎的工程博客编译而来. 简介: 这篇帖子大致描述了日本雅虎在 Goo ...
- 四十二 Python分布式爬虫打造搜索引擎Scrapy精讲—elasticsearch(搜索引擎)的mget和bulk批量操作
注意:前面讲到的各种操作都是一次http请求操作一条数据,如果想要操作多条数据就会产生多次请求,所以就有了mget和bulk批量操作,mget和bulk批量操作是一次请求可以操作多条数据 1.mget ...
- mysql必会必知
select distinct CHARACTER_SET_NAME from CHARACTER_SETS limit 12 offset 30;select distinct CHARACTER_ ...
- Node.js小白开路(一)-- Buffer篇
Buffer是nodeJS中的二进制缓存操作模块内容.先来看一段简短的代码. // 创建一个长度为 10.且用 0 填充的 Buffer. const buf1 = Buffer.alloc(10); ...
- [eShopOnContainers 学习系列] - 02 - vs 2017 开发环境配置
[eShopOnContainers 学习系列] - 02 - vs 2017 开发环境配置 https://github.com/dotnet-architecture/eShopOnContain ...
- react: navigator
1.page js import React from "react"; import {Link} from "react-router-dom"; impo ...
- 【PL/SQL编程】SQL与PL/SQL的区别
SQL概念: SQL是结构化查询语言,由数据定义语言.数据操纵语言.数据控制语言构成,它不面向过程,即前一条语句与后一条语句无关.它没有流程控制,也不存在变量. PL SQL概念: PL/SQL ...
- Java学习笔记——基础篇
Tips1:eclipse中会经常用到System.out.println方法,可以先输入syso,然后eclipse就会自动联想出这个语句了!! 学习笔记: *包.权限控制 1.包(package) ...