通过唯一索引年代锁与X锁来了解MySQL死锁套路

  

在初学者从源码理解MySQL死锁问题中介绍了使用调试MySQL 源码的方式来查看死锁的过程,这篇文章来讲讲一个常见的案例。
  这次我们讲一段唯一索引年代锁与X锁的爱恨情仇

  

我们来看一个简化过的例子
  

        #构造数据   创建表的t1 (   “id”int(11)不是零AUTO_INCREMENT,   “名字”varchar (10),   “水平”int (11),   主键(“id”),   唯一键“uk_name”(“名字”)   );   插入“t1”(“名字”,“水平”)值(' A ', 0);      #出现问题的sql语句如下,并发情况下就会出现死锁   忽略插入“t1”(“名字”,“水平”)值(' A ', 0);   更新t1组水平=1 name=" A ";   之前      

我们用之前介绍过的源码分析方式,先来看下这两条语句分别加什么锁,然后分析死锁形成的过程。
  

  

<强>第一条语句
  

        忽略插入t1(名称、级别)值(' A ', 0),      

在调试中得到的结果如下

  

通过唯一索引年代锁与X锁来了解MySQL死锁套路

  

可以看到这条语句对唯一键uk_name加共享锁(锁),而且成功。
  

  

<强>第二条语句
  

        更新t1组水平=1 name=" A ";之前      

,通过唯一键更新数据库字段。

  

这种情况在之前的文章已经介绍过,<强>会对唯一索引加X锁,然后对主键索引加X锁

  

通过唯一索引年代锁与X锁来了解MySQL死锁套路

  

通过唯一索引年代锁与X锁来了解MySQL死锁套路

  

这样就可以非常轻松的复现死锁的问题了,步骤如下

  

1。开启两个会话,分别开始
  2.session1执行插入忽略t1(名称、级别)值(' A ', 0),
  3.session2执行插入忽略t1(名称、级别)值(' A ', 0),
  4.session1执行更新t1组水平=1 name=" A ";进入等待状态
  5.session2执行更新t1组水平=1 name=" A ";,死锁产生,被回滚,同时事务1执行成功

  

详细的锁状态变化如下

           t1   t2   备注               忽略插入   -   英国t1成功获得的年代锁DB_SUCCESS         -   忽略插入   英国t2成功获得的年代锁DB_SUCCESS         更新   -   英国t1尝试获得的X锁,但没有成功,处于等待状态DB_LOCK_WAIT         -   更新   英国t2尝试获得的X锁,发现死锁产生DB_DEADLOCK         -   死锁   t2释放锁         成功   -   -            

死锁日志如下:

        最新检测到死锁   ------------------------   181208年23:00:52   * * *(1)事务:   事务53 a7、活跃的162秒指数开始阅读   在使用mysql表1,锁定1   锁等待3锁结构(s),堆大小376,2行锁(s)   MySQL线程id 12 0 x700010522000 OS线程处理,查询id 1424 localhost根更新   更新t1组水平=1,name=" A "   * * *(1)等待这个锁被授予:   记录锁空间id 89页4 n位72指数的uk_name表“lock_demo2”。t1的硫氧还蛋白id 53 a7 lock_mode X锁rec但不是差距等   记录锁,2号堆物理记录:n_fields 2;紧凑的格式;信息比特0   0:len 1;十六进制41;asc;;   1:len 4;十六进制80000001;asc;;      * * *(2)事务:   事务53 a8,活跃8秒指数开始阅读   在使用mysql表1,锁定1   3锁结构(s),堆大小376,2行锁(s)   MySQL线程id 96 0 x70001062e000 OS线程处理,查询id 1425根更新本地主机   更新t1组水平=1,name=" A "   * * *(2)持有的锁(S):   记录锁空间id 89页4 n位72指数的uk_name表“lock_demo2”。t1 trx id 53 a8锁定模式年代   记录锁,2号堆物理记录:n_fields 2;紧凑的格式;信息比特0   0:len 1;十六进制41;asc;;   1:len 4;十六进制80000001;asc;;      * * *(2)等待这个锁被授予:   记录锁空间id 89页4 n位72指数的uk_name表“lock_demo2”。t1的硫氧还蛋白id 53 a8 lock_mode X锁rec但不是差距等   记录锁,2号堆物理记录:n_fields 2;紧凑的格式;信息比特0   0:len 1;十六进制41;asc;;   1:len 4;十六进制80000001;asc;;      * * *我们回滚事务(2)      

通过唯一索引年代锁与X锁来了解MySQL死锁套路