开启触发器后qps通常下降15%~40%,高并发下可能跌破50%,因其嵌入事务生命周期,before触发器中查询或跨表操作会增加单条语句0.5–3ms延迟,叠加锁等待与隐式递归链,导致吞吐骤降。

开启触发器后,QPS 通常下降 15%~40%,高并发写入场景下可能跌破 50% —— 这不是理论值,是真实压测反复验证过的区间。
为什么压测时 QPS 掉得比预期更狠
触发器的执行不是“额外加一条 SQL”那么简单,它嵌在事务生命周期里,会拖慢整个语句的完成时间。尤其是 BEFORE INSERT 或 BEFORE UPDATE 触发器,如果里面做了查询、函数调用或跨表操作,MySQL 必须等它彻底跑完才能继续主语句的执行流程。
- 单条语句延迟增加 0.5–3ms 是常态,但对每秒上万次写入来说,毫秒级延迟直接转化为吞吐瓶颈
- 触发器内若含
SELECT(比如查配置表校验),会引发额外锁等待,尤其在READ-COMMITTED隔离级别下容易触发间隙锁竞争 - 如果触发器修改了其他表,还可能触发二级触发器,形成隐式递归链,压测中极难复现但线上偶发雪崩
怎么设计压测才不被误导
很多团队用 sysbench 跑 oltp_insert 就号称“测了触发器性能”,结果偏差极大——因为默认脚本只压单表、无业务逻辑、不模拟真实字段约束。
- 必须用真实业务 SQL 模板:比如插入订单时触发更新用户积分,SQL 中要带
user_id、amount等实际字段,不能只填id和pad - 并发数要分层:先从 16 线程开始,逐步加到 128+,观察 QPS 曲线拐点——多数情况下,触发器带来的衰减在 64 线程后急剧放大
- 务必开启
performance_schema并采集events_statements_history_long,确认慢点是否真落在触发器 SQL 上,而非误判为索引缺失
哪些触发器写法会让压测结果“惨不忍睹”
不是所有触发器都一样重。以下写法在压测中基本等于主动限流:
- 在
AFTER INSERT里调用INSERT INTO audit_log ... SELECT ... FROM big_table WHERE ...—— 大表扫描 + 写日志,I/O 直接拉满 - 触发器内用
UUID()或NOW(6)等非确定性函数,导致 MySQL 无法安全地做 statement-based binlog,被迫切到 row-based,增大主从延迟 - 对同一张表做
UPDATE(比如插入后更新自身状态字段),触发器会报Can't update table 't' in stored function/trigger because it is already used by statement which invoked this stored function/trigger
真正难处理的从来不是“要不要用触发器”,而是“有没有把触发逻辑推到应用层之后再回写数据库”——这点在压测报告里不会体现,但上线后往往才是卡点。











