事务的acid理解

简介

 

    ACID,是指在可靠数据库管理系统(DBMS)中,事务(transaction)所应该具备的四个特性:原子性(Atomicity)、一致性 (Consistency)、隔离性(Isolation)、持久性(Durability).这是可靠数据库所应具有的几个特性.下面针对这几个特性进 行逐个讲解.数据库

理解原子性(Atomicity)

   原子性意味着数据库中的事务执行是做为原子。即不可再分,整个语句要么执行,要么不执行。缓存

   在SQL SERVER中,每个单独的语句均可以看做是默认包含在一个事务之中:服务器

 

因此,每个语句自己具备原子性,要么所有执行,这么所有不执行,不会有中间状态: 
性能

 

 

上面说了,每一条T-SQL语句均可以看做是默认被包裹在一个事务之中的,SQL Server对于每一条单独的语句都实现了原子性,但这种原子粒度是很是小的,若是用户想要本身定义原子的大小,则须要包含在事务中来构成用户自定义的原子粒度: 
spa

 

 

对 于用户来讲,要用事务实现的自定义原子性每每是和业务相关的,好比银行转帐,从A帐户减去100,在B帐户增长100,若是这两个语句不能保证原子性的 话,好比从A帐户减去100后,服务器断电,而在B帐户中却没有增长100.虽然这种状况会让银行很开心,但做为开发人员的你可不但愿这种结果.而默认事 务中,即便出错了也不会整个事务进行回滚。而是失败的语句抛出异常,而正确的语句成功执行。这样会破坏原子性。因此SQL SERVER给予了一些选项来保证事务的原子性.日志

    SQL SERVER提供了两大类方式来保证自定义事务的原子性:orm

  1.经过SET XACT_ABORT ON来设置事务必须符合原子性进程

       利用设置XACT_ABORT选项设置为ON,来设置全部事务都做为一个原子处理.下面例子利用两个语句插入到数据库,能够看到开启SET XACT_ABORT ON选项后,事务具备了原子性: 事务

 

 

2.按照用户设置进行回滚(ROLLBACK)ci

       这种方式具备更高的灵活性,开发人员能够自定义在什么状况进行ROLLBACK,利用TRY CATCH语句和@@ERROR进行判断都属于这种方式. 

 

 

理解一致性(Consistency)

     一致性,即在事务开始以前和事务结束之后,数据库的完整性约束没有被破坏。

     一致性分为两个层面

    1.数据库机制层面

      数据库层面的一致性是,在一个事务执行以前和以后,数据会符合你设置的约束(惟一约束,外键约束,Check约束等)和触发器设置.这一点是由SQL SERVER进行保证的.

 

     2.业务层面

      对于业务层面来讲,一致性是保持业务的一致性.这个业务一致性须要由开发人员进行保证.不少业务方面的一致性能够经过转移到数据库机制层面进行保证.好比,产品只有两个型号,则能够转移到使用CHECK约束使某一列必须只能存这两个型号.

     

理解隔离性(Isolation)

    隔离性。事务的执行是互不干扰的,一个事务不可能看到其余事务运行时,中间某一时刻的数据。

    在Windows中,若是多个进程对同一个文件进行修改是不容许的,Windows经过这种方式来保证不一样进程的隔离性

 

 而SQL Server中,经过SQL SERVER对数据库文件进行管理,从而可让多个进程能够同时访问数据库:

 SQL Server利用加锁和阻塞来保证事务之间不一样等级的隔离性.

    通常状况下,彻底的隔离性是不现实的,彻底的隔离性要求数据库同一时间只执行一条事务,这样的性能可想而知.想要理解SQL Server中对于隔离性的保障,首先要了解事务之间是如何干扰的.

    事务之间的互相影响的状况分为几种,分别为:脏读(Dirty Read),不可重复读,幻读

 

脏读

    脏读意味着一个事务读取了另外一个事务未提交的数据,而这个数据是有可能回滚的,下面来看一个例子:

     两个事务,事务A插入一条数据,但未提交,事务B在此期间进行了读取,读取到了事务A未提交的数据,形成脏读

 

 

不可重复读(Unrepeatable Read)

     不可重复读意味着,在数据库访问中,一个事务范围内两个相同的查询却返回了不一样数据。这是因为查询时系统中其余事务修改的提交而引发的。 

 下面来看一个不可重复读的例子:

     事务B中对某个查询执行两次,当第一次执行完时,事务A对其数据进行了修改。事务B中再次查询时,数据发生了改变:

 

幻读(phantom read)

     幻读,是指当事务不是独立执行时发生的一种现象,例如第一个事务对一个表中的数据进行了修改,这种修改涉及到表中的所有数据行。同时,第二个事务也修改 这个表中的数据,这种修改是向表中插入一行新数据。那么,之后就会发生操做第一个事务的用户发现表中还有没有修改的数据行,就好象发生了幻觉同样. 

 下面来看一个例子:

      事务B更新表中全部的数据,在此期间事务A插入了一条数据,事务B再次查询后,发现竟然还有没有修改的数据,产生幻读:

 

 理解SQL SERVER中的隔离级别

     为 了避免上述几种事务之间的影响,SQL Server经过设置不一样的隔离等级来进行不一样程度的避免。由于高的隔离等级意味着更多的锁,从而牺牲性能.因此这个选项开放给了用户根据具体的需求进行 设置。不过默认的隔离等级Read Commited符合了99%的实际需求.

    SQL Server隔离事务之间的影响是经过锁来实现的,这个概念比较繁杂,因此本文不会详细对这个概念进行讲解.经过阻塞来阻止上述效果

    SQL Server提供了5种选项来避免不一样级别的事务之间的影响

    隔离等级由低到高分别为

    Read Uncommited(最高的性能,但可能出现脏读,不可重复读,幻读)

    Read commited(可能出现不可重复读,幻读)

    Repeatable Read(可能出现幻读)

    Serializable(最低的性能,一次只能执行一个事务,但避免了上述全部状况)

    SNOPSHOT(这个是经过在tempDB中建立一个额外的副原本避免脏读,不可重复读,会给tempDB形成额外负担,由于不是标准ANSI SQL标准,不详细讨论)

 

    总之,不一样的隔离级别是经过加不一样的锁,形成阻塞来实现的,来看一个例子:

    SQL SERVER经过阻塞来阻止脏读,因此保持独立性会以付出性能做为代价:

 

 理解持久性(Durability)

     持久性,意味着在事务完成之后,该事务所对数据库所做的更改便持久的保存在数据库之中,并不会被回滚。

     即便出现了任何事故好比断电等,事务一旦提交,则持久化保存在数据库中.

     SQL SERVER经过write-ahead transaction log来保证持久性。write-ahead transaction log的意思是,事务中对数据库的改变在写入到数据库以前,首先写入到事务日志中。而事务日志是按照顺序排号的(LSN)。当数据库崩溃或者服务器断点 时,重启动SQL SERVER,SQL SERVER首先会检查日志顺序号,将本应对数据库作更改而未作的部分持久化到数据库,从而保证了持久性.

 "若 要了解预写日志的工做原理,最重要的是了解如何将修改的数据写入磁盘。SQL Server 维护当必须检索数据时,将数据页读入的缓冲区高速缓存。数据修改不是直接在磁盘上进行,而是修改高速缓冲存储器中的页副本。直到数据库中出现检查点,或者 必须将修改写入磁盘才能使用缓冲区来容纳新页时,才将修改写入磁盘。将修改后的数据页从高速缓冲存储器写入磁盘的操做称为刷新页。在高速缓存中修改但还没有 写入磁盘的页称为“脏页”。

对 缓冲区中的页进行修改时,将在记录修改的日志高速缓存中生成一条日志记录。在将关联的脏页从高速缓冲存储器刷新到磁盘以前,必须将这条日志记录写入磁盘。 若是在写入日志记录前刷新脏页,则该脏页便会在磁盘上建立修改。若是服务器在将日志记录写入磁盘前失败,则不能回滚此修改。SQL Server 具备防止在写入关联的日志记录前刷新脏页的逻辑。日志记录将在提交事务时写入磁盘。"(MSDN)

总结

    本文简单讲述了ACID的概念和ACID在SQL SERVER中的实现.ACID只是一个理念,并非某项具体的技术.对于健壮数据库来讲,保证ACID是可靠数据库的前提.

相关文章
相关标签/搜索