zoukankan      html  css  js  c++  java
  • 161223、mysql锁的两个例子

    版本:mysql5.5.52  

    存储引擎:InnoDB

    隔离级别:READ-COMMITTED

    示例一:

    事务1:左图      事务2:右图

    1、

    事务2中属于快照读,基于多版本的并发控制协议——MVCC,读取的是记录可见版本,不用加锁,事务1属于当前读,加排它锁,因此事务1虽然未提交,事务2依然可以执行。快照读是mysql InnoDB存储引擎下,隔离级别为READ COMMITTED和REPEATABLE READ时,select语句默认的读取模式。

    2、

    事务1属于当前读,加排它锁,事务2的读取操作也是需要排他锁的,因此读取被阻塞,导致超时,直到事务1提交后,事务2才能读取:

    3、

    事务1属于当前读,加排它锁,但由于隔离级别为READ-COMMITTED,不加gap锁,依然可以插入,如果将隔离级别换成REPEATABLE READ,第一次插入操作被阻塞,直到事务1提交时,插入操作才执行:

    gap就是索引树中插入新记录的空隙,相应的gap lock就是加在gap上的锁,主要是为了防止幻读,只在REPEATABLE READ或以上的隔离级别下的特定操作才会取得gap lock。

    4、

    对于事务1开启后在事务2中插入的记录,由于没有加排它锁,可以直接删除:

    开启前已存在的记录,在事务1中加了排它锁,需等待事务1提交才能在事务2中删除:

    示例二:

    有一个后台的定时任务,定时向第三方发出状态改变请求,同时改变本地数据表的状态,但这个状态是否改变成功是需要第三方确认的,确认的方式是第三方以http请求的形式返回一个处理结果标志(成功或者失败),如果请求没有响应,则重复请求多次,直到我方响应。伪代码如下:

    步骤一

    我方发送状态改变请求:

    @Transaction

    public  void sendChange(int id){

      HttpUtils.send(id,"change");

      statusDao.update(id,"pendSuccess");

      relatedPeopleDao.update(id,"pendFinishRequest");

    }

    步骤二

    我方响应第三方返回的处理结果(方法被web层调用):

    @Transaction

    public void doResponse(int id, String resultStatus){

      relatedPeopleDao.update(id,resultStatus);

      statusDao.update(id,resultStatus);

    }

    这个程序大部分情况是可以正常运行的,因为第三方返回处理结果有一段更长的网络延时,但是否存在这种可能,在方法sendChange开始执行 relatedPeopleDao.update(id,"pendFinishRequest")

    这段代码的时候, 第三方很快返回了处理结果,relatedPeopleDao.update(id,resultStatus)已经执行且持有related_people表相关记录的锁,同时等待status表的锁被释放,但是此时sendChange的一系列操作尚未提交数据库,status的相关记录表仍被事务1持有,两个事务同时持有对方的资源同时在等待对方释放相关的锁,这就产生了死锁现象。

    解决方法之一是在执行doResponse操作之前先检查下related_people表相关记录的状态是否处于合适状态,状态检查是一个普通的select操作,数据库隔离级别为读已提交,因此,如果步骤一中事务未提交,则不会读取到其改变的状态,提交后才能读取到。

    @Transaction

    public void doResponse(int id, String resultStatus){

      if(relatedPeopleDao.isPendFinishRequest(id)){

        relatedPeopleDao.update(id,resultStatus);

        statusDao.update(id,resultStatus);

      }

    }

  • 相关阅读:
    Epplus导出excel
    访问GitHub需要修改hosts
    如何将你的.Net Core程序部署成为服务
    生成雪花Id类
    文件操作帮助类
    工作流-WikeFlow
    《C语言进阶剖析》课程目录
    《C++深度解析》课程目录
    USB URB的status及其代表的意义
    数据结构优秀博文整理
  • 原文地址:https://www.cnblogs.com/zrbfree/p/6241481.html
Copyright © 2011-2022 走看看