您的位置:首页 > 数据库

数据库事务解析及事务四个特性

2016-01-20 11:27 288 查看

   1.数据并发的问题 

    一个数据库可能拥有多个访问客户端,这些客户端都可以并发方式访问数据库。数据库中的相同数据可能同时被多个事务访问,如果没有采取必要的隔离措施,就会导致各种并发问题,破坏数据的完整性。这些问题可以归结为5类,包括3类数据读问题(脏读、幻象读和不可重复读)以及2类数据更新问题(第一类丢失更新和第二类丢失更新)。下面,我们分别通过实例讲解引发问题的场景。

脏读(dirty read) 

    在讲解脏读前,我们先讲一个笑话:一个有结巴的人在饮料店柜台前转悠,老板很热情地迎上来:“喝一瓶?”,结巴连忙说:“我…喝…喝…”,老板麻利地打开易拉罐递给结巴,结巴终于憋出了他的那句话:“我…喝…喝…喝不起啊!”。在这个笑话中,饮料店老板就对结巴进行了脏读。 

A事务读取B事务尚未提交的更改数据,并在这个数据的基础上操作。如果恰巧B事务回滚,那么A事务读到的数据根本是不被承认的。来看取款事务和转账事务并发时引发的脏读场景:

     

[align=center]时间[/align]
[align=center]转账事务A[/align]
[align=center]取款事务B[/align]
T1
 
开始事务
T2
开始事务
 
T3
     
查询账户余额为1000元    
T4
        
取出500元把余额改为500元
T5
查询账户余额为500元(脏读)
 
T6
 
撤销事务余额恢复为1000元
T7
汇入100元把余额改为600元
 
T8
提交事务
 
  在这个场景中,B希望取款500元而后又撤销了动作,而A往相同的账户中转账100元,就因为A事务读取了B事务尚未提交的数据,因而造成账户白白丢失了500元。

不可重复读(unrepeatable read) 

   不可重复读是指A事务读取了B事务已经提交的更改数据。假设A在取款事务的过程中,B往该账户转账100元,A两次读取账户的余额发生不一致:

 
[align=center]时间[/align]
[align=center]取款事务A[/align]
[align=center]转账事务B[/align]
T1
 
开始事务
T2
开始事务
                          
T3
                              
查询账户余额为1000元     
T4
查询账户余额为1000元
                          
T5
                  
取出100元把余额改为900元
T6
 
提交事务                  
T7
查询账户余额为900元(和T4读取的不一致)
 
   在同一事务中,T4时间点和T7时间点读取账户存款余额不一样。
幻象读(phantom read) 

    A事务读取B事务提交的新增数据,这时A事务将出现幻象读的问题。幻象读一般发生在计算统计数据的事务中,举一个例子,假设银行系统在同一个事务中,两次统计存款账户的总金额,在两次统计过程中,刚好新增了一个存款账户,并存入100元,这时,两次统计的总金额将不一致:  

[align=center]时间[/align]
[align=center]统计金额事务A[/align]
[align=center]转账事务B[/align]
T1
 
开始事务
T2
开始事务
             
T3
统计总存款数为10000元
             
T4
 
新增一个存款账户,存款为100元
T5
 
提交事务     
T6
再次统计总存款数为10100元(幻象读)
 
  如果新增数据刚好满足事务的查询条件,这个新数据就进入了事务的视野,因而产生了两个统计不一致的情况。 

  幻象读和不可重复读是两个容易混淆的概念,前者是指读到了其它已经提交事务的新增数据,而后者是指读到了已经提交事务的更改数据(更改或删除),为了避免这两种情况,采取的对策是不同的,防止读取到更改数据,只需要对操作的数据添加行级锁,阻止操作中的数据发生变化,而防止读取到新增数据,则往往需要添加表级锁——将整个表锁定,防止新增数据。

第一类丢失更新 

    A事务撤销时,把已经提交的B事务的更新数据覆盖了。这种错误可能造成很严重的问题,通过下面的账户取款转账就可以看出来: 

    

[align=center]时间[/align]
[align=center]取款事务A[/align]
[align=center]转账事务B[/align]
T1
开始事务
 
T2
 
开始事务
T3
查询账户余额为1000元    
 
T4
 
查询账户余额为1000元
T5
 
汇入100元把余额改为1100元
T6
 
提交事务
T7
取出100元把余额改为900元
 
T8
撤销事务
 
T9
余额恢复为1000元(丢失更新)
 
  A事务在撤销时,“不小心”将B事务已经转入账户的金额给抹去了。 
第二类丢失更新 

  A事务覆盖B事务已经提交的数据,造成B事务所做操作丢失:  

[align=center]时间[/align]
[align=center]转账事务A[/align]
[align=center]取款事务B[/align]
T1
 
开始事务
T2
开始事务
                         
T3
               
查询账户余额为1000元    
T4
查询账户余额为1000元
                         
T5
 
取出100元把余额改为900元
T6
 
提交事务           
T7
汇入100元
 
T8
提交事务
 
T9
把余额改为1100元(丢失更新)
 
    上面的例子里由于支票转账事务覆盖了取款事务对存款余额所做的更新,导致银行最后损失了100元,相反如果转账事务先提交,那么用户账户将损失100元

    2.事务四大特性

一.什么是事务

事务是应用程序中一系列严密的操作,所有操作必须成功完成,否则在每个操作中所作的所有更改都会被撤消。也就是事务具有原子性,一个事务中的一系列的操作要么全部成功,要么一个都不做。

事务的结束有两种,当事务中的所以步骤全部成功执行时,事务提交。如果其中一个步骤失败,将发生回滚操作,撤消撤消之前到事务开始时的所以操作。

二.事务的 ACID

事务具有四个特征:原子性( Atomicity )、一致性( Consistency )、隔离性( Isolation )和持续性( Durability )。这四个特性简称为 ACID 特性。

1 、原子性

事务是数据库的逻辑工作单位,事务中包含的各操作要么都做,要么都不做

2 、一致性

事 务执行的结果必须是使数据库从一个一致性状态变到另一个一致性状态。因此当数据库只包含成功事务提交的结果时,就说数据库处于一致性状态。如果数据库系统 运行中发生故障,有些事务尚未完成就被迫中断,这些未完成事务对数据库所做的修改有一部分已写入物理数据库,这时数据库就处于一种不正确的状态,或者说是 不一致的状态。

3 、隔离性

一个事务的执行不能其它事务干扰。即一个事务内部的操作及使用的数据对其它并发事务是隔离的,并发执行的各个事务之间不能互相干扰。

4 、持续性

也称永久性,指一个事务一旦提交,它对数据库中的数据的改变就应该是永久性的。接下来的其它操作或故障不应该对其执行结果有任何影响。

数据库系统必须维护事务的以下特性 ( 简称 ACID) :

原子性 (Atomicity)

一致性 (Consistency)

隔离性 (Isolation)

持久性 (Durability)

原子性 (Atomicity)

事务中的所有操作要么全部执行,要么都不执行;

如果事务没有原子性的保证,那么在发生系统

故障的情况下,数据库就有可能处于不一致状

态。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: