MySQL触发器如何引发死锁?如何定位锁冲突及提升并发写入效率?

2026-04-30 21:230阅读0评论SEO问题
  • 内容介绍
  • 文章标签
  • 相关推荐

本文共计1255个文字,预计阅读时间需要6分钟。

MySQL触发器如何引发死锁?如何定位锁冲突及提升并发写入效率?

MySQL触发展器本身不开启新事务,但它在父事务上下文中执行,所有SQL操作共享同一事务ID和锁生命周期。一旦触发展器内部包含UPDATE、INSERT或带有FOR UPDATE的查询,就会在原事务基础上新增锁请求。这些锁需要等待整个事务COMMIT或ROLLBACK后才能释放。

常见错误现象:Deadlock found when trying to get lock 报错中,死锁链里总有一个事务的 SQL 显示为触发器内部语句(如 UPDATE order_log SET status = 'processed' WHERE order_id = NEW.id),但应用层日志只记录了主表的 INSERT

  • 触发器中的 DML 不受应用层事务控制粒度约束,容易“偷偷加锁”
  • 若触发器更新的是另一张高频写入表(如统计表、日志表),极易与外部事务形成交叉锁
  • RR 隔离级别下,触发器里的范围查询(如 WHERE created_at > DATE_SUB(NOW(), INTERVAL 1 DAY))会触发 Gap Lock,锁住间隙而非单行

多个触发器级联调用时锁顺序不可控

当一张表上定义了 BEFORE INSERTAFTER INSERT 两个触发器,且后者又去更新第三张表,而该表上也有触发器——这种级联会放大锁路径复杂度。InnoDB 不会为触发器单独做锁排序优化,它只按实际执行顺序加锁。

阅读全文

本文共计1255个文字,预计阅读时间需要6分钟。

MySQL触发器如何引发死锁?如何定位锁冲突及提升并发写入效率?

MySQL触发展器本身不开启新事务,但它在父事务上下文中执行,所有SQL操作共享同一事务ID和锁生命周期。一旦触发展器内部包含UPDATE、INSERT或带有FOR UPDATE的查询,就会在原事务基础上新增锁请求。这些锁需要等待整个事务COMMIT或ROLLBACK后才能释放。

常见错误现象:Deadlock found when trying to get lock 报错中,死锁链里总有一个事务的 SQL 显示为触发器内部语句(如 UPDATE order_log SET status = 'processed' WHERE order_id = NEW.id),但应用层日志只记录了主表的 INSERT

  • 触发器中的 DML 不受应用层事务控制粒度约束,容易“偷偷加锁”
  • 若触发器更新的是另一张高频写入表(如统计表、日志表),极易与外部事务形成交叉锁
  • RR 隔离级别下,触发器里的范围查询(如 WHERE created_at > DATE_SUB(NOW(), INTERVAL 1 DAY))会触发 Gap Lock,锁住间隙而非单行

多个触发器级联调用时锁顺序不可控

当一张表上定义了 BEFORE INSERTAFTER INSERT 两个触发器,且后者又去更新第三张表,而该表上也有触发器——这种级联会放大锁路径复杂度。InnoDB 不会为触发器单独做锁排序优化,它只按实际执行顺序加锁。

阅读全文