背景
因新需求上线,数据量大短时间要计算完,以前的单线程跑不出来,因此改成多线程同时跑,同时会执行 delete update insert 等带锁的SQL
效率改造
开启一个线程池,循环执行扫描到的数据,每个线程独立的事务,测试环境造数据测试,神奇的事发生了居然一次通过,无锁其他问题。
上线后就完犊子了
- 分析原因:分析锁的sql certiNo 普通索引 会重复, dangerNo 未加索引 A线程certino 和B线程certiNo 可能会相同
UPDATE prpldangerunit SET trialCertiNo =? WHERE certiNo = ? and dangerNo=? and validflag='1'
- 加入组合索引 降低锁粒度
当我认为加入这个索引以- 后,就会是行锁了,结果再次打脸,查看了资料,网上建议行锁还是用ID主键索引来进行操作这样能确保锁的粒度是行级的, 那么只好改代码
继续测试继续打脸,好消息是锁的sql 成了insert了
这个SQL锁了就刷新我的认知了,度娘、百度、同事、运维、DBA 都挨着问候了一遍,最后确认是意向锁导致的死锁。
度娘给了三个方案:
- 并行改成串行 (直接淘汰)
- 修改数据库事务隔离级别 (DBA未同意并且发出质疑)
- 并发的情况下一个事务不要多次提交 (正好项目中有这样的操作,谁写的不追究了毕竟人走了。。。走的很安详)
最后保证一丝希望动了代码, 改了会话级别的事务隔离,改成了 读取提交后的级别 这个级别 不会产生间隙锁 所以最后问题完美解决
正则搜索关键字 lock 未发现锁 可能不是最优解决方案, 但是能拔脓的就是好膏药
评论区