- 未提交读(脏读)
- 已提交读
- 可重复读
- 可串行化
未提交读,两个事务之间的每个操作都会影响。当A事务改一个表,在A事务提交前,B事务是可以查询到这个修改的。
已提交读,A事务做出的修改,提交前B事务是不可见的。但是提交了,B事务就可以查询到这个修改了。所以当A事务没提交前,B查询到的结果和A事务提交后B查询的结果是不一致的。这就是不可重复读。
可重复读,可重复读解决了上面的问题,我自己做了些实验,自己总结的一些猜想来说明可重复读。在可重复读的隔离级别,每个事务查询的时候,都会为自己复制一份数据,每次查询的时候就查自己的这份复制。这样就不会有不可重复读的问题,因为每个事务都有自己复制的数据。但是在可重复读的隔离级别,还会有幻读的问题。幻读的定义,感觉网上的说得不清不楚。首先确定一点,在可重复读隔离级别,一个事务修改了一个表,另一个事务是不能再操作这张表的。实验的时候,我发现我修改了一张表,另一个事务操作的时候就一直卡在那。所以可重复读是会锁表的。当A事务添加了一条数据,记住要提交不然B不能修改,B事务去update的时候,会发现多了这条数据。还有其他”奇怪”的现象,总之就是我们操作的数据不是隔离的。做了几次实验后,我觉得原理应该是这样的。当A事务做出修改后,A事务的数据会和B事务原来的数据整合,B修改的数据不是原来复制的数据了。其实是和A事务整合的数据。所以我们以修改复制的数据去想它修改后的结果肯定是不对的。还是用例子来说吧
tableA
id | version |
---|---|
1 | 1.1 |
2 | 1.2 |
3 | 1.3 |
A事务
insert into table value('4','1.4');
update table set version='2' where id='2';
commit;
B事务
update table set version = '1' where id='1'
select * from table
tableB
id | version |
---|---|
1 | 1 |
2 | 2 |
3 | 1.3 |
4 | 1.4 |
tableC
id | version |
---|---|
1 | 1.1 |
2 | 2 |
3 | 1.3 |
4 | 1.4 |
其实A事务修改的不是tableA,而是tableC,tableC就是上面所说的整合的结果。
可串行化
解决了幻读的问题
下面是mysql 查询隔离级别的命令:
select @@global.tx_isolation ,@@Session.tx_isolation
两个字段分别是全局和当前会话的隔离级别
设置当前会话隔离级别:
set session transaction isolation level read committed
set session transaction isolation level read uncommitted
set session transaction isolation level repeatable read