目录
前言
读未提交(Read Uncommitted)
读已提交(Read Committed)
可重复读(Repeatable Read)
串行化(Serializable)
前言
在事物与隔离级别中我们讲解了事务与不同隔离级别,以及可能产生的问题,本节我们通过简单的例子来验证不同隔离级下可能存在的问题。
首先我们需要一张测试表以及初始数据:
create table test_cases
(
id int not null,
group_name varchar(40) not null
unique (id)
);
INSERT INTO health_tree.test_cases (id, group_name) VALUES (1, 'test1');
笔者用的mysql5.7,默认隔离级别是REPEATABLE-READ,可通过“select @@tx_isolation;”查询
可以通过一下命令设置隔离级别
#read uncommitted
#read committed
#repeatable read
#serializable
set session transaction isolation level read uncommitted ;
读未提交(Read Uncommitted)
1、启动事务a
2、启动事务b,并更新数据但不提交
3、事务a再次取数据,可以看到读取到了,事务b未提交的数据
4、若回滚(rollback)事务b
5、事务a读取值变回
这就是未提交读下的脏读现象
读已提交(Read Committed)
1、启动事务a
2、启动事务b,并更新数据但不提交
3、事务a读取数据,数据未变化
4、事务b提交事务
5、事务a读取数据,读取到事务b提交更新的更新数据
虽然读已提交解决了脏读现象,但可能出现不可重复读的问题。
可重复读(Repeatable Read)
1、启动事务a
2、事务b更新数据并提
3、读取事务a,数据未变解决不可重复读问题
4、再次开启事务b,插入一条新数据并提交
5、在事务a中进行相同数据插入
虽然查询并未查询到id为2这条数据,但是在进行插入的时候还是“感知”到这条数据已经存在,这个感知我们可以当作我们一直觉得的“幻读”。这里重点提一下,经常看到对幻读这样的理解:幻读是事务a 执行两次 select 操作得到不同的数据集,即 select 1 得到 1 条记录,select 2 得到 2 条记录,这难到不是不可重复读的表现吗?
正确的理解应该是:事务中 select 操作得到的结果数据状态无法支撑后续的数据操作。比如上面的插入id为 2 的数据是报“ Duplicate entry”。
串行化(Serializable)
相信看到这里大家对mysql事物操作也有了一个基本的掌握,以及对前面的几种隔离级别也有了更深的了解,在这里笔者想把串行化这一点的例子交给读者自己去完成,相信大家看了前面的内容,这部分的操作也可以做到信手拈来,通过实践自己解决“可重复读”隔离级别下产生的幻读问题吧!
相信能耐心读到这里的读者,对mysql技术都有一定的追求,在这里笔者推荐大家阅读:高性能MySQL
电子书版本,扫码回复:mysql