zoukankan      html  css  js  c++  java
  • InnoDb RR隔离级别需要注意的一个坑

    问题

    在并发更新同一行记录场景下(比如调用下游系统可能返回同步结果和异步结果(mq消息),目前更新订单表是通过乐观锁(根据订单原状态做判断)做并发控制):

    开启事务-》更新订单A-》判断update返回值是否>0?继续下面的流程:否则重新查询订单A的状态看是否已经被其他线程更新-如果已经更新到目标状态则正常返回,否则抛出异常

    在批量更新的时候,可能出现异常情况:

    开启事务-》更新订单A-》判断update返回值是否>0?更新订单B(-》更新订单C..):否则重新查询订单A|B|C的状态看是否已经被其他线程更新-如果已经更新到目标状态则正常返回,否则抛出异常

    可能更新订单B|C的情形下查出的结果有时是原状态但是数据库实际上已经更新到目标状态

    实验

    在console1:

    BEGIN;
    select status from Order where id = 'A';
    SELECT SLEEP(10);
    SELECT  status from Order where id = 'B';
    COMMIT
    

    console1的sleep期间在console2执行:

    BEGIN;
    UPDATE Order SET `status` = '失败' where id = 'B'and `status` = '处理中';
    COMMIT;
    

    可看到结果是处理中而非console2执行之后的失败。

    原因

    InnoDb 默认隔离级别是RR,在此级别下,开启事务之后做select属于Consistent Nonlocking Reads,(而update、select for update这类语句属于 locking read),

    RR级别的情况下,开启事务,如果订单A(有并发更新,并)做了select查询那么订单B做select查询的时候的结果仍然是订单A做select查询那一刻的结果

    rc每次快照读时都会去更新事务id数组,rr只在一开始时创建数组

    Reference

    Mysql可重复读

    Transaction Isolation Levels

    Consistent Nonlocking Reads

    locking read

    =====原文作者博客园----dustyhope,转载请注明出处,谢谢
  • 相关阅读:
    Rabbitmq 性能测试
    B+树图文详解
    图的概念和存储(邻接矩阵,邻接表)
    WebApi系列文章
    Asp.Net MVC项目集成Swagger
    正则表达式匹配两个特殊字符中间的内容
    数学常数e的含义
    十大排序算法总结
    C#集合类型大揭秘
    深入System.Web.Caching命名空间 教你Hold住缓存管理(三)
  • 原文地址:https://www.cnblogs.com/liwanping/p/11147155.html
Copyright © 2011-2022 走看看