zoukankan      html  css  js  c++  java
  • MySQL乐观锁为什么可以防止并发

    问题引入

    本文介绍的是最常用的也是mysql默认的innoDB引擎 Read committed隔离级别下事物的并发。这种情况下的事物特点是

    读:在一个事物里面的select语句 不会受到其他事物(不管其他事物有没有commit)的影响。

    写:对一条记录而言,一个事物一旦update一条记录,其他事物只能等待这个事物commit才能update那条记录

    举例并发分析:

    比如表中num字段=10 需要根据num字段的数值做一些业务处理

    事物A  begin   事物B begin  
    select num 得到10   
    根据结果10进行业务处理;  
    处理完之后 num减一 update table set num = num-1;  
    A 事物提交 commit; 此时num是9 此时A已经commit了
      select num 得到10 (此时的查询不受其它事物的影响)
      根据结果10进行业务处理;
      处理完之后 num减一  update table set num = num-1;
      会把num更新成8。
     结论: B以num是10的基础上 处理了众多逻辑,但是到update的时候 用到的b确是9 

    表格中 update table set num = num-1;会受到其他commit事物的影响(B事物把num从9更新成了8) 而select不会(查到的还是10)。

    1利用乐观锁处理事物的并发

      数据库增加一个锁的处理列(版本号),查询的时候多查一个版本号, update的时候 where条件附加一个版本号条件并且更新时候并且把版本号+1,处理流程

      1)select num,version from table;

      2)update table set num=num-1 ,version =version+1 where condition=? version=#{version

      3)Query OK, 1 rows affected (0.04 sec) | 注意:1 rows affected 

         update的时候 where条件附加一个版本号条件并且更新时候并且把版本号+1: update table set num=num-1 ,version =version+1 where condition=? version=#{version} 

      如果出现了查询时候的版本号和where条件的版本号不一致 说明其他事物并发影响到了版本号 version,此时update语句的影响行数(Query OK, 1 rows affected (0.04 sec))是0 然后做异常处理。()

    2把计算放到SQL中

    当我们把计算逻辑(比如钱的增量)写在SQL里面的时候 可以不用乐观锁,因为SQL增量时会读到其他已经提交的事物。

    注意:一条记录,一个事物update还未提交的时候,其他时候只能等待这个事物commit完成才能update

    乐观锁处理并发的原理 重点

    当事物的隔离级别是REPEATABLE_READ情况下:当前事物不能select到并发事物中已经提交的事物。

    当事物的隔离级别是READ COMMITTED情况下:当前事物select到并发事物中已经提交的事物。

    1)一个事物中的select语句可能不会收到其他事物的影响,也就是可能查不到其他并发中未提交的事物(即使提交了 如果是REPEATABLE_READ也查不到)。所以两个事物共同执行时产生了并发的冲突。

    2)虽然这个被并发的字段通过select查不出来,但是在where条件语句中 这个字段会受到其他事物的影响 。所以可以利用这点 可以读到并发事物影响的数据 ,从而做出判断,防止并发。

    补充:共享锁与排他锁

    --共享锁:对某一资源加共享锁,自身可以读该资源,其他人也可以读该资源

    (也可以再继续加共享锁,即 共享锁可多个共存),但无法修改。要想修改就必须等所有共享锁都释放完之后。语法为:

    select * from table lock in share mode

    --排他锁:对某一资源加排他锁,自身可以进行增删改查,其他人无法进行任何操作。语法为:

    select * from table for update (A select for update的时候 B可以select 但不能select for update  排它锁只有一把)

    数据库的增删改操作默认都会加排他锁,而查询不会加任何锁。

  • 相关阅读:
    apache和tomcat有什么不同,为什么要整合apache 和tomcat
    使用jstack分析cpu消耗过高的问题
    eclipse建立springMVC 简单项目
    JAVA中的反射机制
    MySQL索引的Index method中btree和hash的优缺点
    JAVA中的线程安全与非线程安全
    Java中普通代码块,构造代码块,静态代码块执行顺序
    jvm的内部体系结构浅析
    CPU思考
    linux内核调度算法(2)--CPU时间片如何分配 转!
  • 原文地址:https://www.cnblogs.com/ssskkk/p/8673374.html
Copyright © 2011-2022 走看看