脏读,不可重复读,幻读及事务隔离等级


脏读,不可重复读,幻读及事务隔离等级

网上查了很多文章,对脏读,不可重复读,幻读以及几个隔离等级都有了基本的讲解。不过都只是讲三个情况出现的原因及表现形式,提高隔离等级就能避免,而没讲提高隔离等级后是用什么方式杜绝的。所以花时间大致研究了下,总结出表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事务查询出来的数据,在事务中的多次查询中,是完全一致的,数据不会变,不会少,也不会多。
是最强隔离等级,事务严格按序列挨个执行(所以叫序列化或串行化),并发性最低。
× × ×