分析事务的隔离级别

Posted Alighieri

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了分析事务的隔离级别相关的知识,希望对你有一定的参考价值。

  在DBMS中,事务保证了一个操作序列可以全部执行或者全部不执行(原子性),从一个状态撞边到另外一个状态(一致性)。由于事务满足持久性。所以一旦事务被提交之后,数据就能被持久化下来,又因为事务是满足隔离性的,所以,当多个事务同时处理同一个数据的时候,多个事务是互不影响的。所以,在多个事务并发操作的过程中,如果控制不好隔离级别,就可能产生脏读,不可重复读或者幻读等现象

  在数据库事务的ACID四个属性中,隔离性是最放松的一个。可以在数据操作过程中利用数据库的锁机制或者多版本并发控制机制获取更高的隔离等级。但是,随着数据库隔离级别的提高,数据的并发能力也有所下降。所以,如何在并发性和隔离性之间做一个很好的权衡就成了一个直观重要的问题。

  在软件开发中,几乎每类这样的问题都会有多种最佳实践来供参考,很多DBMS定义了多个不同的“事务隔离等级”来控制锁的成都和并发能力。

  ANSI/ISO SOL定义的标准隔离级别有四种,从高到底依次为:可序列化、可重复读、提交读、未提交读。

  1、未提交读:最低的隔离级别。在这种事务隔离级别下,一个事务可以读到另外一个事务未提交的数据

  

  实现原理:事务在读数据的时候并未对数据加锁,事务在修改数据的时候支队数据增加行级共享锁

  

  现象:事务1读取某行记录时,事务2也能对这行记录进行读取、更新(因为事务1并未对数据增加任何锁)

  当事务2对该记录进行更新时,事务1再次读取该记录,能读到事务2对该记录的修改版本(因为事务二只增加了共享读锁,事务1可以再增加共享读锁读取数据),即使该修改尚未被提交

  事务1更新某行记录时,事务2不能对这行记录做更新,知道事务1结束。(因为事务1对数据增加了共享读锁,事务2不能增加排他写锁进行数据的修改)

  

  2、提交读:在一个事务修改数据过程中,如果事务还没提交,其他事务不能读取该数据

  数据库锁的情况:

    1、事务对当前被读取的数据加行级共享锁(当读到时才加锁),一旦读完该行,立即释放该行级共享锁

    2、事务在更新某数据的瞬间(就是发生更新的瞬间),必须先对其加行级排他锁,直到事务结束才释放

  现象:

    1、事务1在读取某行记录的整个过程中,事务2都可以对该行记录进行读取(因为事务1对该行记录增加行级共享锁的情况下,事务2同样可以对该数据增加共享锁来读数据)

    2、事务1读取某行的一瞬间,事务2不能修改该行数据,但是,只要事务1读取完该行数据,事务2就可以对该行数据进行修改。(事务1在读取的一瞬间会对数据增加共享锁,任何其他事务都不能对该行数据增加排他锁。但是事务1只要读完该行数据,就会释放行级共享锁,一旦锁释放,事务2就可以对数据增加排他锁并修改数据)

    3、事务1更新某行记录时,事务2不能对这行记录做更新,直到事务1救赎。(事务1在更新数据的时候,会对该行数据增加排他锁,直到事务结束才会释放锁,所以,在事务2没有提交之前,事务1都不能对数据增加共享锁进行数据的读取。所以,提交读可以解决脏读的现象)

  

  可重复读:由于提交读隔离级别会产生不可重复读的读现象。所以,比提交读更高一个级别的隔离级别就可以解决不可重复读的问题。这种隔离级别就叫可重复读

  数据库锁情况:

    1、事务在读取某数据的瞬间(就是开始读取的瞬间),必须先对其加行级共享锁,直到事务结束才释放

    2、事务在更新某数据的瞬间(就是发生更新的瞬间),必须先对其加行级排他锁,直到事务结束才释放

  现象:

    1、事务1在读取某行记录的整个过程中,事务2都可以对该行记录进行读取(因为事务1对该行记录增加行级共享锁的的情况下,事务2同样可以对该数据增加共享锁来读数据)

    2、事务1在读取某行记录的整个过程中,事务2都不能修改该行数据(事务1在读取的整个过程会对数据增加共享锁,直到事务提交才会释放锁。所以整个过程中,热河其他事务都不能对该行数据增加排他锁。所以,可重复读能够解决不可重复读的现象)

    3、事务1更新某行记录时,事务2不能对这行记录做更新,直到事务1结束。(事务一在更新数据的时候,会对该行数据增加排他锁,知道事务结束才会释放锁,所以,在事务二没有提交之前,事务一都能不对数据增加共享锁进行数据的读取。所以,提交读可以解决脏读的现象)

 

  可序列化 

  可序列化(Serializable)是最高的隔离级别,前面提到的所有的隔离级别都无法解决的幻读,在可序列化的隔离级别中可以解决。我们说过,产生幻读的原因是事务一在进行范围查询的时候没有增加范围锁(range-locks:给SELECT 的查询中使用一个“WHERE”子句描述范围加锁),所以导致幻读。

  数据库锁情况   

  1、事务在读取数据时,必须先对其加 表级共享锁 ,直到事务结束才释放;

  2、事务在更新数据时,必须先对其加 表级排他锁 ,直到事务结束才释放。

  现象:

  1、事务1正在读取A表中的记录时,则事务2也能读取A表,但不能对A表做更新、新增、删除,直到事务1结束。(因为事务一对表增加了表级共享锁,其他事务只能增加共享锁读取数据,不能进行其他任何操作)

  2、事务1正在更新A表中的记录时,则事务2不能读取A表的任意记录,更不可能对A表做更新、新增、删除,直到事务1结束。(事务一对表增加了表级排他锁,其他事务不能对表增加共享锁或排他锁,也就无法进行任何操作)

虽然可序列化解决了脏读、不可重复读、幻读等读现象。但是序列化事务会产生以下效果:

  1.无法读取其它事务已修改但未提交的记录。

  2.在当前事务完成之前,其它事务不能修改目前事务已读取的记录。

  3.在当前事务完成之前,其它事务所插入的新记录,其索引键值不能在当前事务的任何语句所读取的索引键范围中

以上是关于分析事务的隔离级别的主要内容,如果未能解决你的问题,请参考以下文章

深入分析事务的隔离级别

[中级]深入分析事务的隔离级别

数据库事务隔离标准分析

分析事务的隔离级别

[数据库事务与锁]详解三: 深入分析事务的隔离级别

[数据库事务与锁]详解三: 深入分析事务的隔离级别