博客园 :: 首页 :: 博问 :: 闪存 :: 新随笔 :: 联系 :: 订阅 订阅 :: 管理 ::

一般大家都对事务的四种隔离模式比较熟悉,从松到严依次是:

- 读取未提交(Read uncommitted):处于此模式下可能会出现脏读、幻象读、不可重复读
- 读取已提交(Read committed):处于此模式下可能会出现幻象读、不可重复读
- 可重复读(Repeatable read):处于此模式下可能会出现幻象读
- 串行(Serialize):不会出现幻象读
 
那么脏读、幻象行、不可重复读是什么意思呢?
- 脏读:其它的事务(执行单个 select 语句也算一个事务)可以读取到某个事务更新(包括插入和删除)了但未提交的数据。脏读是应用中应该避免的,因为读取的是不可靠的数据(我觉得把这个叫做幻象行更形象,实际却不是)。一般数据库不会设定为这个模式,但有时候也会用到。脏读的好处是读取时不会对表或记录加锁,可以绕开写队列的排队,避免了等待。如在一个更新特别频繁的表中要选择表中所有的数据,就可以显示指定隔离级别:
select .... at isolation 0
 
- 不可重复读:这是描述在同一个事务中两条一模一样的 select 语句的执行结果的比较。如果前后执行的结果一样,则是可重复读;如果前后的结果可以不一样,则是不可重复读。这个特性从字面上也能看出来。
     不可重复读的模式下首先不会出现脏读,即读取的都是已提交的数据。在一个事务中,读取操作是不会加排他锁的,当下一条一模一样的 select 语句的执行时,命中的数据集可能已经被其它事务修改了,这时候,还能读到相同的内容吗?
     因此,要达到可重复读的效果,数据库需要做更多的事情,比如,对读取的数据行加共享锁,并保持到事务结束,以禁止其它事务修改它。这样会降低数据库的性能。而隔离级别的串行则比可重复读更严格。一般数据库的的隔离级别只设置到读取已提交。这是兼顾了可靠性和性能的结果。
     上面还只提到了对命中的数据行加锁,以防止其它事务修改它。但没有提到,如果其它事务增加了符合条件的数据行怎么办?有些数据库对这种情况新定义了两个级别:读取稳定性和游标稳定性。前者不限制新增符合条件的数据行,而后者则阻止新增这样的数据行。
 
- 幻象读:是指两次执行同一条 select 语句会出现不同的结果,第二次读会增加一数据行,并没有说这两次执行是在同一个事务中。一般情况下,幻象读应该正是我们所需要的。但有时候却不是,如果打开的游标,在对游标进行操作时,并不希望新增的记录加到游标命中的数据集中来。隔离级别为 游标稳定性 的,可以阻止幻象读。
 
posted on 2015-08-17 14:52  黑米  阅读(11912)  评论(0编辑  收藏  举报