欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

MySQL,产生死锁的问题dead lock

程序员文章站 2022-05-29 16:48:36
...
首先,其实造成死锁的可能性也许每个人都不一样,所以重点不是如何解决问题,而是分析,也许我遇到的问题并不适用于其他人,但是遇到这种情况先要搞清楚,是哪个表,的哪个字段产生了资源征用,然后分析解决就可以了。

登录mysql后,通过show engine innodb status;来查看最后一次死锁的情况

查询后显示的
------------------------
LATEST DETECTED DEADLOCK
------------------------
块下面就是死锁的征用描述信息

里面会描述事物1、事物2....在执行某一语句的时候,对哪一个表的哪一个字段进行征用资源的时候,被什么类型的锁占用了

比如如下信息

RECORD LOCKS space id 47 page no 305 n bits 328 index PRIMARY of table `test`.`t_test` trx id 13806 lock_mode X locks gap before rec insert intention waiting

这里描述了
锁的类型,RECORD,锁得模式X,在准备申请插入意向锁的时候,在PRIMARY主键索引所在的空间47 页号305的328位的位置上产生了征用。


这里就要先熟悉几个概念
锁模式,X代表排它锁,S代表共享锁,IX代表表级排他锁,IS代表表级共享锁,他们之间在多线程/会话/事务的情况下,有可能同时使用,具体兼容关系可以参看官方文档
http://dev.mysql.com/doc/refman/5.5/en/innodb-locking.html

锁的类型也在上面的文档里有描述
RECORD 为记录级锁
GAP为记录区间范围的锁
Next-Key Locks为大于值,小于等于某个值的区间范围的锁
这些指的都是索引,其实也就是在操作表数据的时候,会先将索引锁住,尤其是PRIMARY和UNIQUE,这种唯一约束的索引,在操作的时候,数据库都会先查询数据库中的索引然后再进行相应操作。


了解了这些我们就可以分析,锁的资源征用情况
比如如下操作

表模型为
主键(自增,有主键索引)
其他列

开始事务1
事务1,执行delete语句删除某一个存在的值(锁住这条记录的索引)
事务1,插入一条新的记录,申请锁,等待这个锁被授权
开始事务2
事务2,执行delete语句删除某一个与事务1不同的存在的值(锁住这条记录的索引)
事务2,插入一条新的记录,申请锁,等待这个锁被授权
提交事务1
提交事务2

以上的操作不会造成资源竞争,因为两条delete删除的是指定的id的值。

但是当上面的操作,如果delete删除某一个不存在的值,那么就会将这个不存在的索引在所有索引里面去找,会找到一个区间范围,比如索引是10,20,要删除15,那么就会将索引10~20的范围进行锁死,而与此同时,另外一个事务也要锁这个区间范围,就会造成资源竞争。
两个事务的insert都在等待delete锁定的区间范围释放,然后执行插入,这样就造成了死锁

当然以上的只是其中一种情况,造成死锁的原因就是资源竞争,所以先查清楚哪个资源被竞争,执行哪一条语句时造成可,以及表的结构是怎样的很重要。