触发器对写入性能的真实伤害是QPS断崖下跌、WAL暴增和锁竞争飙升;并发压测才能暴露问题,单条语句耗时不具参考性。

触发器对写入性能的影响无法靠单条语句耗时判断,真实伤害体现在QPS断崖式下跌、WAL暴增和锁竞争飙升上——压测必须跑并发,否则根本测不出来。
看QPS拐点比看慢日志更准
slow_query_log里通常找不到触发器慢的痕迹,因为MySQL默认不记录触发器内SQL的执行时间。真正信号是:并发从16线程加到64线程时,QPS突然掉20%以上;再加到128线程,可能直接掉40%+。这不是线性衰减,而是锁竞争和WAL写放大叠加的结果。
- 务必开启
long_query_time = 0抓全量日志,再用EXPLAIN FORMAT=TREE确认主SQL是否隐式触发了全表扫描 - 查
SHOW ENGINE INNODB STATUS,盯innodb_row_lock_time_avg是否异常升高 - 在
performance_schema.events_statements_history_long中搜TRIGGER关键字,确认是否有大量触发事件堆积
监控WAL和事务膨胀程度
一个 INSERT INTO t VALUES (1),(2),(3) 本该是1次事务提交,有AFTER触发器就变成3次独立事务+3次binlog写入+3次行锁申请。这直接导致I/O随机化、主从延迟上涨、Innodb_os_log_written 指标凸起。
- MySQL:监控
Innodb_rows_updated和Handler_update比值,若接近1:1,说明每行UPDATE都额外触发了操作 - PostgreSQL:查
pg_stat_bgwriter的buffers_checkpoint和buffers_clean是否突增 - 批量导入(如
LOAD DATA INFILE)前必须禁用触发器,否则50万行=50万次小事务,顺序IO变随机IO
识别隐式锁等待链和索引缺失
触发器最危险的不是慢,而是它悄悄把锁范围扩大、把查询拖成全表扫,且你完全看不到源头。比如 UPDATE stats SET cnt = cnt + 1 WHERE type = NEW.type,如果 stats(type) 没索引,每次更新都锁全表。
- MySQL 8.0+ 必须查
performance_schema.data_locks,确认锁是否因缺失索引而升级为表级或间隙锁 - 用
EXPLAIN直接执行触发器内的SQL,重点看type字段是否为ALL或index - 禁止在触发器里写
SELECT COUNT(*) FROM big_table WHERE user_id = OLD.user_id这类语句——没索引=每改一行扫一遍
真正难调的从来不是语法,而是某条没走索引的SELECT、一次没控制深度的嵌套、或一个本该异步却硬塞进事务的INSERT。评估触发器影响,本质是在测它如何把“单次写入”变成“多次锁+多次WAL+多次上下文切换”。


















