是,触发器会实时同步拖慢insert/update/delete,因主语句必须等待触发器逻辑执行完毕;性能损耗主要来自大表select、跨库写入、复杂函数调用及after中更新原表等操作。

触发器会拖慢 INSERT/UPDATE/DELETE 吗
会,而且影响是实时的、同步的。MySQL 在执行 INSERT、UPDATE 或 DELETE 时,如果对应表上有触发器,必须等触发器逻辑全部执行完,主语句才算完成。这意味着:哪怕触发器只做一条 INSERT INTO log_table,主操作的响应时间也会增加该语句的执行耗时。
常见错误现象包括:
- 批量导入变慢,原本 2 秒完成的
LOAD DATA INFILE,加了触发器后变成 15 秒 - 高并发写入时出现锁等待加剧,因为触发器里的语句可能持有额外的行锁或表锁
-
SHOW PROCESSLIST中看到大量Updating或Writing to net状态卡在触发器逻辑上
触发器里哪些操作最伤性能
不是所有触发器都一样慢,性能损耗主要来自触发器体内执行的具体动作。以下几类要特别小心:
- 对大表做
SELECT(尤其是没走索引的)—— 触发器内查 10 万行,每次 INSERT 都查一遍,等于放大 10 万倍 I/O - 跨库或跨表写入(如往日志库写记录)—— 增加网络往返或事务协调开销
- 调用存储函数(
SELECT my_func(new.id)),尤其函数内部含循环或复杂计算 - 在
AFTER触发器里再更新原表(比如AFTER UPDATE又去改同一张表),可能引发递归或死锁
一个典型反例:AFTER INSERT ON orders 触发器里执行 UPDATE stats SET total = (SELECT COUNT(*) FROM orders) —— 每次下单都全表扫描统计,完全不可扩展。
如何判断触发器是不是性能瓶颈
不能靠猜,得用 MySQL 自带工具定位:
- 开启
slow_query_log并设置long_query_time = 0,抓取所有语句,观察触发器相关 SQL 是否频繁出现在慢日志里 - 用
performance_schema查触发器执行耗时:SELECT EVENT_NAME, COUNT_STAR, SUM_TIMER_WAIT FROM performance_schema.events_statements_summary_by_event_name WHERE EVENT_NAME LIKE '%trigger%';
- 对比关闭触发器前后的
sys.schema_table_statistics,看目标表的rows_affected和avg_timer_wait是否显著上升
注意:MySQL 不会把触发器单独记为“一条语句”,它的耗时会被合并进主语句的执行时间里,所以必须结合 performance_schema 或慢日志中的完整 SQL 文本分析。
替代触发器的更高效方案
如果只是想实现审计、缓存更新、状态同步等目的,多数时候有比触发器更可控、更低侵入的方式:
- 应用层统一写日志:在业务代码中,
INSERT成功后再发一条异步消息(如 Kafka / RabbitMQ),由消费者写日志表 —— 解耦、可重试、不拖慢主流程 - 用
binlog解析(如 Canal、Maxwell)捕获变更,实现最终一致性同步,避免事务内阻塞 - 对统计类需求,改用定时聚合(如每 5 分钟跑一次
REPLACE INTO daily_stats),而不是每次写都算 - 真需要强一致性且无法改架构?至少把触发器逻辑精简到只做单条
INSERT,并确保目标表有合适索引和分区策略
真正难处理的是那些隐式依赖触发器业务逻辑的老系统——删掉它可能让下游数据错乱,但留着又扛不住增长。这时候得先做 performance_schema 数据采集,量化每毫秒花在哪,再决定是重构、拆分还是加缓存兜底。











