MYSQL 根据唯一索引键更新死锁问题解析
作者:凯恩血蹄LOKTA
mysql 死锁问题及死锁权重分析
问题发生过程:
1、生产发现死锁一次
语句为sql1:UPDATE table set data = ‘123’ where business_no = 'ABC';
该行数据的id=1, business_no = 'ABC'
tablbe 字段
id:主键 business_no为唯一索引字段,其他字段暂时无意义
2、查找发生死锁问题原因
上述sql在一个事务内,死锁必定有两把锁。
最开始对锁的理解就是锁主键、不清楚是否有其他锁参与。
网上搜索发现update的where条件为唯一索引时候,sql会同时获取两把锁,先获取唯一索引business_no的锁,再获取主键id的锁,所以必定同一时刻有先获取id锁,再获取唯一主键锁的sql。
查找代码返现同一时刻,另外一个事务2执行了以下sql
sql2:UPDATE table set data = ‘123’ where id = 1;
sql3:UPDATE table set data = ‘123’ where business_no = ‘ABC’;
现在发现了死锁原因:
但是现象不复核预期
sql 1 先唯一键锁、后 主键锁
sql2 先主键锁 、sql3后唯一键锁
理论是sql1 和 sql3 都有可能发生死锁,因为sq1在一个sql内,sql2、slq3是分开的,
按预期sql3发生死锁错误的概率最大,但是代码发生了8次死锁全部是sql1发生了死锁。
3、为啥sql1发生死锁
第一步怀疑有其他sql参与了,但是没找到疑点sql。
网上搜索发现了一个死锁权重的概念。
大概意思是发生死锁根据算法确定权重,权重小的事务会回滚。
感觉问题快找到了,猜想sql1事务内只有一个事务(他基本就是小权重的事务)。
那接下来分析日志验证:
事务2还执行了以下sql。
sql4:UPDATE table2 set data2 = ‘123’ where id = 1;
在sql2和sql3之前还有sql4。
那猜测有事务4 中sql5 UPDATE table2 set data2 = ‘345’ where id = 1;
让后搜索日志发现同一时间有有sql5。
接下来实际验证:
开启事务1:
执行:sql2:UPDATE table set data = ‘123’ where id = 1;
执行sql4:UPDATE table2 set data2 = ‘123’ where id = 1;
开启事务2:
执行slq1:UPDATE table set data = ‘123’ where business_no = 'ABC';
开启事务3:
执行sql5:UPDATE table2 set data2 = ‘345’ where id = 1;
事务1:
执行slq3:UPDATE table set data = ‘123’ where business_no = ‘ABC’;
发现必sql1必死锁异常且回滚,问题解决。
4、问题总结
msql行级锁加锁的过程。
mysql发生死锁回滚的机制。
到此这篇关于MYSQL 根据唯一索引键更新死锁问题的文章就介绍到这了,更多相关mysql唯一索引键更新死锁内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!