脏读,不可重复读,幻读及事务隔离等级
脏读,不可重复读,幻读及事务隔离等级
网上查了很多文章,对脏读,不可重复读,幻读以及几个隔离等级都有了基本的讲解。不过都只是讲三个情况出现的原因及表现形式,提高隔离等级就能避免,而没讲提高隔离等级后是用什么方式杜绝的。所以花时间大致研究了下,总结出表2内容,大概说明了提高隔离等级后,不同事务之间是怎样的执行方式。
概念 | 现象 | 出现条件 | 解决办法 |
---|---|---|---|
脏读 | 读取到了别的事务未提交(Commit)的数据,而读取到的数据可能会回滚(Rollback),所以得到的数据可能是假数据,故称为脏读 | 隔离等级为Uncommitted | 将隔离等级提升至Committed |
不可重复读 | 事务中两次查询结果不一致。原因:A事务的两次查询过程中,B事务修改/删除(并且Commit)了A事务查询出来的数据 | 隔离等级为Committed及以下 | 将隔离等级提升至Repeatable |
幻读 | 事务中两次查询结果条数不一致。原因:A事务的两次查询过程中,B事务新增(并且Commit)了符合A事务查询条件的数据。一般认为幻读是不可重复读的一种特殊形式。 | 隔离等级为Repeatable及以下 | 将隔离等级提升至Serializable |
事务级别 | 特点/实现方式 | 脏读 | 不可重复读 | 幻读 |
---|---|---|---|---|
Uncommitted | 可以读取别的事务没有提交而可能回滚的数据,造成脏读。 并发性最高,在查询时不会等待其他事务完成。在SQL Server中,等同于 select ... with (nolock) |
√ | √ | √ |
Committed | 只能读取其他事务已提交的数据。如果有其他未完成的事务,则不能获得查询结果(被阻塞)。必须等待所有事务都结束,才能返回查询结果。避免了脏读。 但是A事务已查询出来的数据,可以被B事务能修改/删除,造成了A事务两次相同语句查询出来的结果不一致(字段值变动或数据条数减少),即不可重复读。也会造成幻读。 是SQL Server的默认隔离等级 |
× | √ | √ |
Repeatable | A事务的查询过程中(A事务未结束),B事务不能修改或删除A事务中查询出来的数据,必须等待A事务结束(B事务被阻塞)。避免了不可重复读, 保证A事务已经查询出来的数据,不会被其他事务修改或删除,确保一致性。 但是B事务可以新增符合A事务查询条件的数据。从而会造成幻读。即A事务在B事务新增前后查询出来的结果数目不同,数据变多。 是MySQL的默认隔离等级 |
× | × | √ |
Serializable | A事务查询过程中(A事务未结束),B事务至少不能新增/修改/删除符合A查询条件内的任何数据,必须等待A事务结束(B事务被阻塞)。也有可能不能增/删/改A事务查询条件外的数据。保证了A事务查询出来的数据,在事务中的多次查询中,是完全一致的,数据不会变,不会少,也不会多。 是最强隔离等级,事务严格按序列挨个执行(所以叫序列化或串行化),并发性最低。 |
× | × | × |