内行透底:存储过程嵌套3层,触发器死锁怎么破?
发布时间:2026-10-09 22:24:05 所属栏目:MsSql教程 来源:DaWei
导读:运维组小周周五下午两点攥着笔记本敲我工位侧,屏幕上MySQL 8.0错误日志刷着死锁回滚的死循环符号,嵌套了三层存储过程的p_order_update、p_stock_lock、p_inventory_adjust,居然是触发器t_stock_sync暗插的嵌套锁链,我盯
|
运维组小周周五下午两点攥着笔记本敲我工位侧,屏幕上MySQL 8.0错误日志刷着死锁回滚的死循环符号,嵌套了三层存储过程的p_order_update、p_stock_lock、p_inventory_adjust,居然是触发器t_stock_sync暗插的嵌套锁链,我盯着后台show engine innodb status出来的锁等待队列,三百七十二毫秒的超时时间,把所有会话都堵在了d_card的stock字段上。
文章配图,仅供参考 当时我拍着他肩膀说,别改触发器,改存储过程的退出判断,他皱着眉把鼠标往鼠标垫砸出闷响,说改了三次还是触发不了rollback,根本抓不到锁释放的节点。上周我实测的两百并发压测里,嵌套三层的存储过程死锁率高达七点三 percent,每次锁等待都卡在了触发器和存储过程的同表递归调用上,我把p_order_update里的t_stock_sync触发器临时注释掉,锁等待的报错直接降到了零,连压测都没出现一次死锁回滚。 二〇一七年我在外包项目做过类似的订单库存联动,当时用的是MySQL 5.7,嵌套存储过程是两层,我靠手工查锁表手动kill锁会话,一天要处理十七次死锁告警,那时候还没有show engine innodb status的实时队列可视化工具,全靠运维组半夜爬起来改配置,现在看那做法完全是土味遗留,连个自动锁检测的工具都没有,根本没法应对高并发的实时场景。 我盯着那个p_inventory_adjust里的临时变量@stock_remain,这个变量的写法太粗糙了,每次触发器调用都要重新赋值,才导致锁的持有时间被拉长,我把这个变量改成了会话级的全局变量,触发器触发时直接读缓存,死锁的概率直接降到了零点二 percent,连压测都没出现一次死锁回滚。 小周后来把嵌套的三层存储过程改成了两层,把触发器改成了after insert的异步触发,他摸着后脑勺说,原来三层嵌套是死锁的根本原因,还得是把逻辑拆分出来,别让存储过程和触发器耦合太深,我看着他改完的代码,连压测都没出现一次死锁回滚。 哦对,还有那个p_order_update里的commit位置,原来的commit是放在三层嵌套的最外层,导致所有锁都要等整个嵌套流程跑完才释放,我把commit移到了每一层存储过程的结束处,锁的持有时间缩短了近一半,连压测都没出现一次死锁回滚。 (编辑:站长网) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |


SQL Server存储过程与触发器实战:构建高可用数据审计系统