是,mysql触发器会实时拖慢insert/update/delete。它在事务内同步执行,每行触发一次,含跨表操作、函数调用或锁等待时延迟更显著,且失败导致整个事务回滚。

MySQL触发器会拖慢 INSERT/UPDATE/DELETE 吗
会,而且影响是实时、不可绕过的。触发器代码在事务内同步执行,主 SQL 没跑完,触发器就卡在那——不是“可能慢”,是“一定多花时间”。尤其当触发器里有 INSERT INTO another_table 或调用 UUID()、NOW() 这类函数时,延迟更明显。
常见错误现象:SHOW PROCESSLIST 里看到大量 Updating 或 Writing to net 状态卡住;写入 QPS 突降,而 CPU 和磁盘 IO 并不饱和;从库延迟飙升(因为触发器逻辑也得重放)。
- 触发器运行在主 SQL 的同一事务中,失败则整个事务回滚
- 每个匹配行都会单独执行一次触发器体,
INSERT INTO t VALUES (1),(2),(3)会触发 3 次BEFORE INSERT - 触发器里不能用
SELECT ... FOR UPDATE或其他显式加锁语句,会报错Can't update table 't' in stored function/trigger - 如果触发器里写日志表,建议用
INSERT DELAYED(5.6+ 已废弃)或改用异步队列,否则日志表成瓶颈
BEFORE vs AFTER 触发器性能差别大吗
差别不大,但语义和风险完全不同。性能开销主要来自触发器体内的 SQL 和计算,而不是“before”或“after”这个时机本身。真正影响性能的是:你在这个时机里干了什么。
使用场景差异很关键:BEFORE INSERT 常用于修正字段值(比如自动补 created_at),开销小;AFTER INSERT 如果要查新插入的记录再关联更新另一张表,就会多一次主键查找 + 一次 UPDATE,延迟翻倍。
-
BEFORE可修改NEW行数据,适合默认值、校验、转换——轻量操作首选 -
AFTER才能安全读取刚插入的自增 ID(NEW.id),但此时主记录已落盘,再做跨表操作容易引发锁竞争 - 不要在
AFTER UPDATE里对原表再做UPDATE t SET x = ... WHERE id = NEW.id,会触发递归(除非关掉log_bin_trust_function_creators且显式禁用)
触发器里调用存储函数或外部服务会怎样
直接让写入变成串行化瓶颈。MySQL 不允许触发器里发起网络请求,但如果你封装了个 UDF(用户自定义函数)去调 HTTP,或者用 SYS_EVAL 类扩展,不仅极不安全,还会把整个写入线程堵死——一个慢请求,全表写不进去。
更常见的“伪外部调用”是查另一个数据库实例(比如用 FEDERATED 表),这等于把本地事务拖进分布式协调,超时、锁等待、连接池耗尽全找上门。
- 所有函数必须是 deterministic(确定性)的,否则无法开启 binlog(报错
This function has none of DETERMINISTIC...) -
MD5()、SHA1()可用,但长文本哈希会吃 CPU;RAND()不被允许,除非声明NOT DETERMINISTIC且关 binlog 校验(不推荐) - 避免在触发器里
SELECT COUNT(*) FROM huge_table,统计类查询没索引就扫全表,写个 10 行都等 2 秒
怎么判断某个触发器是不是性能罪魁祸首
别猜,用 performance_schema 实锤。MySQL 5.7+ 默认开启,查 events_statements_history_long 能看到每条 SQL 对应的触发器调用栈,包括耗时。
简单定位法:SET profiling = 1; 执行一条带触发器的 INSERT,再 SHOW PROFILES; 看总耗时;接着 SHOW PROFILE FOR QUERY N;,重点看 Trigger 那一行是否占了 70%+ 时间。
- 检查
information_schema.TRIGGERS确认触发器是否启用(STATUS = 'ENABLED') - 临时禁用:重命名触发器名(MySQL 不支持
DROP TRIGGER IF EXISTS直接删,但可CREATE TRIGGER new_name ...覆盖) - 压测对比:用
sysbench写入时,分别开关触发器,看queries per second和95th percentile latency变化
最常被忽略的一点:触发器不会出现在慢查询日志里,它被包裹在主 SQL 下面。你看到一条 INSERT 耗时 300ms,实际可能是触发器里一个没走索引的 UPDATE 搞的鬼。











