2014年6月23日星期一

Cloud_022:数据库事务特性以及隔离级别说明

之所以整理这篇东东,是为了将来和NoSQL中的事务做一个比较,以及和数据网格中的事务做一个比较。

数据库事务具有ACID四个特性:原子性(Atomicity)、一致性(Consistency)、隔离性(Isolation)、持久性(Durability)。

1. 原子性(Atomicity)
原子性是指事务是一个不可再分割的工作单位,事务中的操作要么都发生,要么都不发生。

2. 一致性(Consistency)
一致性是指在事务开始之前和结束以后,数据库的完整性约束(唯一约束、外键约束、Check约束、触发器设置)没有被破坏。

3. 隔离性(Isolation)
隔离性是指多个事务并发操作数据时,事务之间是隔离的,一个事务不会影响其它事务运行结果。
多个事务同时操作相同的数据时,每个事务都有自己独立的数据空间,各个事务之间是隔离的。
隔离性的实现原理是锁和阻塞。

可以为数据库设置不同的隔离级别,不同的级别对隔离性的保障不同,对性能的影响也不同。

多个事务并发操作数据时,可能会产生如下问题:
(1)脏读(Dirty Reads)
脏读指的是一个事务读取了另一个事务未提交的数据。
比如事务A修改了数据但未提交,此时事务B读取了事务A修改后的数据,然后事务A回滚了。
(2)不可复读(Non-Repeatable Reads)
不可复读指的是在一个事务范围内前后两次相同的查询却返回了不同数据。
这是由于在前后两次相同的查询期间,另一个事务修改了数据,并且提交了。
(3)幻读(Phantom Reads)
幻读指的是当事务不是独立执行时发生的一种现象。
事务A对一个表中的数据进行了修改,这种修改涉及到表中的全部数据行。
事务B向同一个表中插入一行新数据。
事务A发现表中还有未修改的数据行,好象发生了幻觉一样。
(4)丢失更新
丢失更新指的是两个事务同时读取同一条记录,A先修改记录,B也修改记录(B不知道A修改过),B提交数据后,B的修改结果覆盖了A的修改结果。

以上问题可以通过设置隔离级别来得到不同程度的解决:
(1)未提交读(Read Uncommited):在读数据时不会检查或使用任何锁。因此,在这种隔离级别中可能读取到没有提交的数据。
SELECT语句以非锁定方式被执行,所以有可能读到脏数据,隔离级别最低。
(2)已提交读(Read commited):只读取提交的数据并等待其他事务释放排他锁,读数据的共享锁在读操作完成后立即释放。解决了脏读问题,但未解决不可复读。已提交读是大多数数据库的默认隔离级别。
(3)可重复读(Repeatable Read):和已提交读类似,但是读数据时会保持共享锁直到事务结束。解决了不可复读问题,但未解决幻读问题。
(4)可串行读(Serializable):和可重复读的类似,但它不仅会锁定受影响的数据,还会锁定这个范围。这就阻止了新数据插入查询所涉及的范围。
所有SELECT语句都被隐式的转换成SELECT ... LOCK IN SHARE MODE,即读取使用表级共享锁,读写相互都会阻塞。隔离级别最高。

总结各个隔离级别如下:
隔离级别 
脏读  
丢失更新
不可重复读
 幻读 
 并发模型
更新冲突检测
未提交读:Read Uncommited
悲观
已提交读:Read commited
悲观
可重复读:Repeatable Read
悲观
可串行读:Serializable
悲观

4. 持久性(Durability)
持久性是指在事务完成以后,该事务所对数据库所做的更改持久化的保存在数据库之中。
持久性的实现原理是通过提前把操作日志记录下里,这样即使突然断电,数据库重启之后,检查日志,把未持久化的数据写到数据库中。

参考文献:
1. http://blog.csdn.net/shuaihj/article/details/14163713
2. http://h2appy.blog.51cto.com/609721/771768/
3. http://www.cnblogs.com/malaikuangren/archive/2012/04/06/2434760.html
4. http://blog.csdn.net/sunxing007/article/details/6427290

没有评论: