标签:
1. read uncommitted,读未提交。事务A能读取到事务B已修改但未提交的数据。脏读
2. read committed,读已提交。事务A只能读取到事务B已经提交的数据,但由于事务读取到的是它每次SELECT前的数据快照,因此同一事务多次SELECT的结果可能不同。不可重复读。大多数关系数据库(如Oracle)的默认隔离等级
3. repeatable read,可重复读。事务A只能读取到事务B已经提交的数据,且同一事务每次读取到的数据均相同。这是因为事务读取到的是事务开始时的数据快照,同一事务中只有一份且保持不变直到事务结束。但是,由于数据快照生成于事务开始时,若不同事务已修改而未提交的数据存在冲突(主键/唯一键冲突等),则后执行修改的事务会被挂起直到先执行修改的事务提交,但读取不到造成冲突的数据,即幻读
例如:表T有唯一键UK,事务A先向T插入UK=x但不提交,事务B再向T插入UK=x,此时事务B会被挂起;若事务A提交,此时事务B会因为唯一键冲突而报错;若事务A删除UK=x后提交,此时事务B的插入操作会成功;然而直到事务B提交之前,它都SELECT不到由事务A插入的UK=x。这是MySQL的默认隔离等级
4. serializable,序列化。事务必须串行执行,完全隔离
综上:
首先,隔离等级是针对事务的SELECT操作而言的
其次,隔离等级是按照不隔离(脏读)=>不可重复读=>可重复读但存在幻读=>完全串行化(禁用并发,解决幻读),逐步加强隔离的程度的
另:
网上对幻读的理解存在很多错误的地方。如:
有些文章引用《高性能MySQL》中所讲,MySQL的InnoDB引擎通过MVCC(多版本并发控制)在repeatable read级就已解决了幻读的问题。实际是错误的,MVCC采用类似乐观锁的机制从原理上就无法解决幻读,同时从上面的例子中也可以看出,幻读问题在repeatable read级并未解决
有些文章采用了类似这样的描述:当事务(A)读取了一定范围的数据后,另一个事务(B)在这个范围中插入一些数据,当原事务(A)在这个范围内更新数据的时候,就会“惊奇”地发现这些数据,如同“幻影”一般。这种描述很模糊,什么叫“惊奇”,什么叫“幻影”?结合前面所举的例子可以看出,事务A之所以会“惊奇”地感知到这些数据,是因为它SELECT不到这些由事务B更新的数据,但这些数据会影响到A的操作,如同“幻影”一样,看不到它,但它却已经存在
最后,总结一下便于记忆,对于事务而言:
“读未提交”是指不管其它事务是否提交都能读到它们的数据
“读已提交”是指只有当其它事务提交之后才能读到它们的数据
“可重复读”是指只有当自己提交了之后才能读到其它事务提交的数据
“序列化”是指事务逐个执行,当前事务提交之前,其它都被挂起
标签:
原文地址:http://blog.csdn.net/sadfishsc/article/details/46564647