侧边栏壁纸
博主头像
MDZZW博主等级

曾经也是帅哥,如今只是肉多

  • 累计撰写 28 篇文章
  • 累计创建 26 个标签
  • 累计收到 7 条评论

记录一次MySQL并发insert导致死锁

MDZZW
2021-12-15 / 0 评论 / 0 点赞 / 1,047 阅读 / 518 字
温馨提示:
本文最后更新于 2022-10-26,若内容或图片失效,请留言反馈。部分素材来自网络,若不小心影响到您的利益,请联系我们删除。

背景

因新需求上线,数据量大短时间要计算完,以前的单线程跑不出来,因此改成多线程同时跑,同时会执行 delete update insert 等带锁的SQL

效率改造

开启一个线程池,循环执行扫描到的数据,每个线程独立的事务,测试环境造数据测试,神奇的事发生了居然一次通过,无锁其他问题。

上线后就完犊子了
image.png

  • 分析原因:分析锁的sql certiNo 普通索引 会重复, dangerNo 未加索引 A线程certino 和B线程certiNo 可能会相同
UPDATE prpldangerunit     SET trialCertiNo =?   WHERE     certiNo = ? and dangerNo=? and validflag='1'
  • 加入组合索引 降低锁粒度
    image.png

当我认为加入这个索引以- 后,就会是行锁了,结果再次打脸,查看了资料,网上建议行锁还是用ID主键索引来进行操作这样能确保锁的粒度是行级的, 那么只好改代码

image.png

继续测试继续打脸,好消息是锁的sql 成了insert了
image.png

这个SQL锁了就刷新我的认知了,度娘、百度、同事、运维、DBA 都挨着问候了一遍,最后确认是意向锁导致的死锁。
度娘给了三个方案:

  1. 并行改成串行 (直接淘汰)
  2. 修改数据库事务隔离级别 (DBA未同意并且发出质疑)
  3. 并发的情况下一个事务不要多次提交 (正好项目中有这样的操作,谁写的不追究了毕竟人走了。。。走的很安详)

最后保证一丝希望动了代码, 改了会话级别的事务隔离,改成了 读取提交后的级别 这个级别 不会产生间隙锁 所以最后问题完美解决
image.png

正则搜索关键字 lock 未发现锁 可能不是最优解决方案, 但是能拔脓的就是好膏药
image.png

0

评论区