关于ACID中的I即隔离性(Isolation),
配合姊妹篇事务的四大基本要素(即ACID原则)效果更佳




这篇文章讲解十分清晰

例子很赞

从上到下,隔离级别逐渐增强



  • 第一级隔离级别: 未提交读: Read uncommitted

事务A用来修改某条记录,事务B包含查询该记录的操作;

(如A是修改余额,B是查询当前余额,进行判断,如果大于某个值,则再进行查询,将结果写入另外的一张日志表)

当事务A修改记录但还未执行,事务B执行读取到了事务A修改后的记录;

这就是脏读(Dirty Read)



  • 第二级隔离级别: 已提交读: Read committed

(绝大多数数据库,包括Sql Server/Oracle的默认隔离级别)

事务B要等事务A提交后才能读取数据,这样就能解决上面的脏读问题,但引入了新的问题:

事务B执行,查询出该条记录(第一次),进行判断,符合条件;这时事务A执行,修改(扣减)余额,这个过程中B想再次查询该记录(第二次),必须等A执行完才能再读;等A执行结束B再去读取时,发现查出来的数据与第一次竟然不同

“这就是已提交读,若有事务对数据进行更新(UPDATE)操作时,读操作事务要等待这个更新操作事务提交后才能读取数据,这样可以解决脏读问题;

但却可能出现”一个事务范围内“的两次相同的查询却返回了不同数据,这带来了新问题,也就是不可重复读…



  • 第三级隔离级别: 可重复读: Repeatable read

(MySql的默认隔离级别)

可重复读,即在开始读取数据(事务开启)时,不再允许修改(update)操作;

即事务B开启后,不允许其他事务(此处即A)的UPDATE操作;

可重复读可以解决不可重复读问题;

“不可重复读对应的是修改,即update操作。但是可能还会有幻读问题。

因为幻读问题对应的是插入insert操作(或删除操作),而非update操作。

解决不可重复读的问题只需锁住满足条件的行,解决幻读需要锁表



  • 第四级隔离级别: 串行化: Serializable

在开始读取数据(事务开启)时,不再允许修改(update)操作,但还可以进行insert和delete操作;

假设事务C需要扫描全表,进行判断,将其中符合条件的写入另外一张表;

开启事务,第一次查询时,扫到全表有100条记录;这时恰巧有一个insert操作,新插入了一条数据,该次事务C执行到第二次查询时,发现成了101条记录,似乎出现了幻觉,这就是幻读;

Serializable 是最高的事务隔离级别,在该级别下,事务串行化顺序执行,可以避免脏读、不可重复读与幻读。但是这种事务隔离级别效率低下,比较耗数据库性能,一般不使用。