zoukankan      html  css  js  c++  java
  • 事务隔离级别的简单理解

    ANSI/ISO SQL标准定义了4种事务隔离级别,这些隔离级别是根据事务并行出现的4个“现象”定义的。

    4个现象是:

    1.更新丢失(Lost Update):A和B同时写

    例: 
    1.事务A将数值改为1并提交; 
    2.事务B将数值改为2并提交。 
    这时数据的值为2,事务A所做的更新将会丢失。

    解决办法:对行加锁,只允许并发一个更新事务。

    2.脏读(dirty read):A改后还未提交,B读,A又改并提交

    例:

    1.Mary的原工资为1000, 财务人员将Mary的工资改为了8000(但未提交事务) 
    2.Mary读取自己的工资 ,发现自己的工资变为了8000,欢天喜地! 
    3.而财务发现操作有误,回滚了事务,Mary的工资又变为了1000, 像这样,Mary记取的工资数8000是一个脏数据。


    3.不可重复读(nonrepeatable read):A先读,B再改,A再读

    例:

    1.在事务A中,Mary 读取了自己的工资为1000,操作并没有完成 
    2.在事务B中,这时财务人员修改了Mary的工资为2000,并提交了事务. 
    3.在事务A中,Mary 再次读取自己的工资时,工资变为了2000 
    解决办法:如果只有在修改事务完全提交之后才可以读取数据,则可以避免该问题。

    4.幻读(phantom read):A改后还未提交,B改其他的,A再查

    例:

    1.A把所有的“黑色”改为“白色”

    2.B把所有的“红色”改为“黑色”

    3.A再查询黑色,却发现还有一批。

    根据对4个现象的避免程度,事务的4个隔离级别是:

      • 1.Read Uncommited :读未提交数据(会出现脏读,不可重复读,幻读)
      • 2.Read Commited :读已提交的数据(会出现不可重复读,幻读)
      • 3.Repeatable Read :可重复读(会出现幻读)
      • 4.Serializable :串行化

    数据库事务的隔离级别有4个,由低到高依次为Read uncommitted、Read committed、Repeatable read、Serializable,这四个级别可以逐个解决脏读、不可重复读、幻读这几类问题。

    √: 可能出现    ×: 不会出现

      脏读 不可重复读 幻读
    Read uncommitted
    Read committed ×
    Repeatable read × ×
    Serializable × × ×

    注意:我们讨论隔离级别的场景,主要是在多个事务并发的情况下,因此,接下来的讲解都围绕事务并发。

    Read uncommitted 读未提交

    公司发工资了,领导把5000元打到singo的账号上,但是该事务并未提交,而singo正好去查看账户,发现工资已经到账,是5000元整,非常高兴。可是不幸的是,领导发现发给singo的工资金额不对,是2000元,于是迅速回滚了事务,修改金额后,将事务提交,最后singo实际的工资只有2000元,singo空欢喜一场。


    出现上述情况,即我们所说的脏读,两个并发的事务,“事务A:领导给singo发工资”、“事务B:singo查询工资账户”,事务B读取了事务A尚未提交的数据。

    当隔离级别设置为Read uncommitted时,就可能出现脏读,如何避免脏读,请看下一个隔离级别。

    Read committed 读提交

    singo拿着工资卡去消费,系统读取到卡里确实有2000元,而此时她的老婆也正好在网上转账,把singo工资卡的2000元转到另一账户,并在singo之前提交了事务,当singo扣款时,系统检查到singo的工资卡已经没有钱,扣款失败,singo十分纳闷,明明卡里有钱,为何......

    出现上述情况,即我们所说的不可重复读,两个并发的事务,“事务A:singo消费”、“事务B:singo的老婆网上转账”,事务A事先读取了数据,事务B紧接了更新了数据,并提交了事务,而事务A再次读取该数据时,数据已经发生了改变。

    当隔离级别设置为Read committed时,避免了脏读,但是可能会造成不可重复读。

    大多数数据库的默认级别就是Read committed,比如Sql Server , Oracle。如何解决不可重复读这一问题,请看下一个隔离级别。

    Repeatable read 重复读

    当隔离级别设置为Repeatable read时,可以避免不可重复读。当singo拿着工资卡去消费时,一旦系统开始读取工资卡信息(即事务开始),singo的老婆就不可能对该记录进行修改,也就是singo的老婆不能在此时转账。

    虽然Repeatable read避免了不可重复读,但还有可能出现幻读。

    singo的老婆工作在银行部门,她时常通过银行内部系统查看singo的信用卡消费记录。有一天,她正在查询到singo当月信用卡的总消费金额(select sum(amount) from transaction where month = 本月)为80元,而singo此时正好在外面胡吃海塞后在收银台买单,消费1000元,即新增了一条1000元的消费记录(insert transaction ... ),并提交了事务,随后singo的老婆将singo当月信用卡消费的明细打印到A4纸上,却发现消费总额为1080元,singo的老婆很诧异,以为出现了幻觉,幻读就这样产生了。

    注:Mysql的默认隔离级别就是Repeatable read。

    Serializable 序列化

    Serializable是最高的事务隔离级别,同时代价也花费最高,性能很低,一般很少使用,在该级别下,事务顺序执行,不仅可以避免脏读、不可重复读,还避免了幻像读。

  • 相关阅读:
    Azure PowerShell (2) 修改Azure订阅名称
    Windows Azure Platform Introduction (11) 了解Org ID、Windows Azure订阅、账户
    Azure PowerShell (3) 上传证书
    Azure PowerShell (1) PowerShell入门
    Windows Azure Service Bus (2) 队列(Queue)入门
    Windows Azure Service Bus (1) 基础
    Windows Azure Cloud Service (10) Role的生命周期
    Windows Azure Cloud Service (36) 在Azure Cloud Service配置SSL证书
    Android studio 使用心得(一)—android studio快速掌握快捷键
    android 签名、混淆打包
  • 原文地址:https://www.cnblogs.com/eric-qin/p/5911799.html
Copyright © 2011-2022 走看看