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 ...
随机推荐
- Codeforces Round #363 (Div. 2) A、B、C
A. Launch of Collider time limit per test 2 seconds memory limit per test 256 megabytes input standa ...
- 《PHP对象、模式与实践》之对象
1.php与对象 知识点: a.关于引用赋值 $other = &$my_obj;//按照引用复制,指向相同对象. 例子: <?php $my_obj = 1; echo $my_obj ...
- php 后台接受POST值
[场景描述]:展示型企业站制作管理后台,前端框架:vue.js2.0,bootstrap,后台语言:php [问题描述]:使用管理后台向接口发送请求时,接口使用PHP的$_POST['args'],接 ...
- 给virtualbox里linux添加共享文件夹
首先,必须要有已经在VirtualBox中安装好的Ubuntu系统,才能按照以下步骤操作,具体怎样在VirtualBox中安装Ubuntu系统百度经验里已经有很多,大家可以自己查询参照. 打开虚拟 ...
- 腾讯开源手游热更新方案,Unity3D下的Lua编程
原文:http://www.sohu.com/a/123334175_355140 作者|车雄生 编辑|木环 腾讯最近在开源方面的动作不断:先是微信跨平台基础组件Mars宣布开源,腾讯手游又于近期开源 ...
- mvvm2
1:设计模式 在MVP模式中,为了让UI层能够从逻辑层上分离下来,设计师们在UI层与逻辑层之间加了一层interface.无论是UI开发人员还是数据开发人员,都要尊重这个契约.按照它进行设计和开发.这 ...
- Codeforces Round #448 (Div. 2)C. Square Subsets
可以用状压dp,也可以用线型基,但是状压dp没看台懂... 线型基的重要性质 性质一:最高位1的位置互不相同 性质二:任意一个可以用这些向量组合出的向量x,组合方式唯一 性质三:线性基的任意一个子集异 ...
- Neutron的安全组原理
Security group通过Linux IPtables来实现,为此,在Compute节点上引入了qbr*这样的Linux传统bridge(iptables规则目前无法加载到直接挂在到ovs的 ...
- 对无序数组的并发搜索的java实现
对无序数组的并发搜索的实现可以充分的用到多cpu的优势 一种简单的策略是将原始数组按照期望的线程数进行分割,如果我们计划使用两个线程进行搜索,就可以把一个数组分成两个,每个线程各自独立的搜索,当其中有 ...
- sublime 非常好用的注释工具
Sublime在进行前端开发时非常棒,当然也少不了众多的插件支持,DocBlocker是在Sublime平台上开发一款自动补全代码插件,支持JavaScript (including ES6), PH ...