触发器会显著增加锁等待,因其在事务内执行DML操作,导致隐式锁扩张、锁范围变大、持有时间延长,进而引发Lock wait timeout exceeded;可通过查询INNODB_TRX和SHOW ENGINE INNODB STATUS定位,推荐用异步+幂等或INSERT … ON DUPLICATE KEY UPDATE替代。
触发器确实会显著增加锁等待,尤其在高并发写入场景
是的,MySQL 触发器本身不直接“加锁”,但它在事务内执行时,会把触发逻辑里的 DML 操作(如 UPDATE、INSERT、SELECT ... FOR UPDATE)合并进主事务的锁生命周期。这意味着:原本一个简单的 INSERT 可能只持有一行 X 锁,加上触发器后,可能额外请求 1~3 次行锁甚至间隙锁,锁持有时间变长、锁范围变大,自然抬高了其他事务的等待概率。
为什么触发器让 Lock wait timeout exceeded 更常见
根本原因在于“隐式锁扩张”和“锁顺序不可控”。比如一个 AFTER INSERT 触发器去更新汇总表 stats_counter:
- 若
stats_counter.group_id没有索引,UPDATE ... WHERE group_id = ?会升级为全表扫描 + 行锁,甚至 GAP LOCK,大幅延长锁持有时间 - 多个事务并发插入不同记录但命中同一
group_id,就会排队争抢同一行——后到的事务等前一个事务提交,超时即报Lock wait timeout exceeded - 触发器中调用子查询或函数,若该查询未走索引,也会扩大扫描范围,间接拉长锁等待链
怎么快速验证触发器是不是罪魁祸首
别靠猜,直接查 INFORMATION_SCHEMA.INNODB_TRX 和死锁日志: