一、概述
隔离级别 | 脏读(Dirty Read) | 不可重复读(NonRepeatable Read) | 幻读(Phantom Read) |
读未提交(Read uncommitted) | √ | √ | √ |
读已提交(Read committed) | × | √ | √ |
可重复读(Repeatable read) | × | × | √ |
串行读(Serializable) | × | × | × |
二、脏读&不可重复读&幻读概念
1. 脏读(Dirty Read)-读取未提交数据
A事务读取了B事务未提交的数据,此时B发生错误执行了回滚,此时A事务读取到的数据就是脏数据。
例子如下:
2. 不可重复读(UnRepeatable Read)-前后多次读取,内容不一致
A事务读取了一行记录,紧接着B事务修改了A事务刚才读取的那一行记录,然后A事务再次读取了这行记录,发现与刚才读取的结果不同。
例子如下:
3. 幻读(Phantom Read)-前后多次读取,数据总量不一致
A事务在执行读取操作,第一次查询数据总量后,B事务执行了新增数据操作并提交事务后,A事务再次查询数据总量,发现相比于第一次数据总量不一样。
例子如下:
不可重复读和幻读的区别
- 不可重复读是读取了其他事务更改的数据,针对的是update操作。
- 解决办法:使用行级锁,锁定该行,事务多次读取操作完成后释放该行锁,这个时候才允许其他事务更改刚才的数据。
- 幻读是读取了其他事务新增的数据,针对的是insert、delete操作。
- 解决办法:使用表级锁,锁定整张表,事务多次读取总量操作完成后释放该表锁,这个时候才允许其他事务新增数据。
三、事务隔离级别
1. 读未提交(Read uncommitted)
最低级别的隔离级别,允许脏读,也就是可能读取到其他事务中未提交事务修改的数据。
2. 读已提交(Read committed)
被读取的数据可以被其他事务修改,这样可能导致不可重复读。也就是说,事务读取的时候获取读锁,但是在读完之后立即释放(不需要等事务结束),而写锁则是事务提交之后才释放,释放读锁之后,就可能被其他事务修改数据。该等级也是SQL Server默认的隔离等级。
3. 可重复读(Repeatable read)
所有被Select获取的数据都不能被修改,这样就可以避免一个事务前后读取不一致的情况。但是没有办法控制幻读,因为这个时候其他事务不能更改所选的数据,但是可以增加数据。InnoDB默认级别。
4. 串行读(Serializable)
所有事务一个接着一个的执行,这样可以避免幻读。对于基于锁来实现并发控制的数据库来说,串行化要求在执行范围查询的时候,需要获取范围锁,如果不是基于锁实现并发控制的数据库,则检查到有违反串行操作的事务时,需回滚该事务。