概述
死锁原因:隔离级别、GAP锁、索引的顺序及业务逻辑
尽量使用较低的隔离级别,比如如果发生了间隙锁,你可以把会话或者事务的事务隔离级别更改为 RC(read committed)级别来避免,但此时需要把 binlog_format 设置成 row 或者 mixed 格式
精心设计索引,并尽量使用索引访问数据,使加锁更精确,从而减少锁冲突的机会;
选择合理的事务大小,小事务发生锁冲突的几率也更小;
给记录集显示加锁时,最好一次性请求足够级别的锁。比如要修改数据的话,最好直接申请排他锁,而不是先申请共享锁,修改时再请求排他锁,这样容易产生死锁;
不同的程序访问一组表时,应尽量约定以相同的顺序访问各表,对一个表而言,尽可能以固定的顺序存取表中的行。这样可以大大减少死锁的机会;
一、不同表相同记录行锁冲突
这种情况很好理解,事务A和事务B操作两张表,但出现循环等待锁情况
二、相同表记录行锁冲突
这种情况比较常见,之前遇到两个job在执行数据批量更新时,jobA处理的的id列表为[1,2,3,4],而job处理的id列表为[8,9,10,4,2],这样就造成了死锁。
三、gap锁冲突
innodb在RR级别下,如下的情况也会产生死锁,比较隐晦。不清楚的同学可以自行根据上节的gap锁原理分析下。
四、不同索引锁冲突
这种情况比较隐晦,事务A在执行时,除了在二级索引加锁外,还会在聚簇索引上加锁,在聚簇索引上加锁的顺序是[1,4,2,3,5],而事务B执行时,只在聚簇索引上加锁,加锁顺序是[1,2,3,4,5],这样就造成了死锁的可能性。
五、死锁检测
wait-for graph原理
我们怎么知道上图中四辆车是死锁的?他们相互等待对方的资源,而且形成环路!我们将每辆车看为一个节点,当节点1需要等待节点2的资源时,就生成一条有向边指向节点2,最后形成一个有向图。我们只要检测这个有向图是否出现环路即可,出现环路就是死锁!这就是wait-for graph算法。
六、死锁检测命令
#1、查看正在进行中的事务
SELECT *
FROM information_schema.INNODB_TRX
#2、查看正在锁的事务
SELECT *
FROM INFORMATION_SCHEMA.INNODB_LOCKS;
#3、查看等待锁的事务
SELECT *
FROM INFORMATION_SCHEMA.INNODB_LOCK_WAITS;
#4、查询是否锁表
SHOW OPEN TABLES
WHERE In_use > 0;
#在发生死锁时,这几种方式都可以查询到和当前死锁相关的信息。
#5、查看最近死锁的日志
SHOW ENGINE innodb STATUS
最后
以上就是香蕉香氛为你收集整理的MySQL死锁的全部内容,希望文章能够帮你解决MySQL死锁所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复