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,转载请注明出处,谢谢
  • 相关阅读:
    2.SpringMVC入门
    1.SpringMVC回顾MVC
    10.spring声明式事务
    9.spring整合Mybatis
    maven项目的classpath路径对应的文件目录
    8.spring中的AOP
    Java通过反射破解单例模式和防止反射破解单例模式案例
    7.代理模式
    让Java项目默认使用jdk8等级进行编译
    return false取消手机移动端的默认设置
  • 原文地址:https://www.cnblogs.com/liwanping/p/11147155.html
Copyright © 2011-2022 走看看