理解事务的隔离性
理解事务的隔离性
事务是以可控的方式对数据资源进行访问的一组操作。其属性包括原子性、一致性、隔离性和持久性,也就是常说的ACID。其中,隔离性是针对数据资源的并发访问,规定了各个事务之间相互影响的程度。个人认为这是事务的4个特性里面,比较难理解的一个。
事实上,事务的隔离性可以分为4种类型的隔离级别:Read Uncommitted,Read Committed, Repeatable Read和Serilization。这4个类型的隔离级别在应对数据资源并发访问可能出现的问题时的要求不一样。数据资源并发访问时可能出现的问题有:
www.zzzyk.com
1. 脏读:如果一个事务A对数据进行了更改,但是还没有提交,而另一个事务B就可以读到事务A尚未提交的更新结果。这样,当事务A进行回滚时,那么事务B开始读到的数据就是一笔脏数据。
2. 不可重复读:同一个事务在事务过程中,对同一个数据进行读取操作,读取到的结果不同。例如,事务B在事务A的更新操作前读到的数据,跟在事务A提交此更新操作后读到的数据,可能不同。
要避免不可重复读,需要将事务所操作的记录都加上锁,不允许其他事务对此记录进行写操作。
3. 幻读:同样一个查询在整个事务中多次执行,查询所得的结果不同。例如,事务A对全部记录做了更新操作,尚未提交前,事务B又插入了一条记录,那么事务A再次读取数据库时,会发现还有一条记录(即事务B新插入的记录)没有做更新。
www.zzzyk.com
也可以理解成:
要避免脏读,需要控制在事务没有提交更新前,其他事务无法看到此事务的更新结果。
要避免脏读,需要控制在事务没有提交更新前,其他事务无法看到此事务的更新结果。
要避免幻读,需要将整张表都锁住了。
对于隔离级别:
Read Uncommitted:最低的隔离级别。一个事务可以读取另一个事务没有提交的更新结果。
Read Committed:一个事务的更新操作只有在提交了之后,才会被另一个事务读取到同一笔数据更新后的结果
Repeatable Read:在整个事务中,对同一笔数据的读取结果是相同的,不管其他事务是否同时在对这笔数据进行更新,也不管这笔更新是否提交。
Serilizable:所有的事务操作都必须串行操作。这种隔离级别最高,但是牺牲了系统的并发性。通常会使用其他的隔离级别加上相应的并发锁机制来控制对数据的访问。
事务的隔离级别与数据资源并发访问时的问题的对应关系可以如下表所示:
www.zzzyk.com
脏读
不可重复读
幻读
Read Uncommited
可能
可能
可能
Read commited
不可能
可能
可能
Repeatable Read
不可能
不可能
可能
Serilization
不可能
不可能
不可能
www.zzzyk.com
总体来说,隔离级别与系统并发性成反比,与数据一致性成正比。一般数据库默认的隔离级别是:ReadCommited,不同数据库支持的隔离级别可能不一样。为了实现数据一致性和系统并发行的平衡,一般会采取Read Committed加上锁表等方式来进行。
相应的资料还可以查看:
《Spring揭秘》,第17章,认识事务本身
不可重复读与幻读有什么区别 http://topic.csdn.net/u/20070729/15/819e7042-3fbf-4550-930a-27cc8b4d282b.html
作者 sunandice