是,触发器易致CPU飙升,主因是“算得多”:含子查询、JOIN、隐式转换、自定义函数、递归触发及FOR EACH ROW批量执行等,均会引发全表扫描或链式反应。

会,而且往往是“算得多”导致的CPU飙升,不是“写得多”。
触发器里执行子查询或JOIN就容易拉高CPU
MySQL触发器在事务内同步执行,所有SQL逻辑都走完整解析、优化、执行流程。哪怕只是SELECT name FROM users WHERE id = NEW.user_id,如果users(id)没索引或类型不匹配(比如INT vs BIGINT),实际执行计划可能是type: ALL——每插一行就全表扫一次。
- 用
EXPLAIN查触发器内SQL,不能只查主语句;得从performance_schema.events_statements_history_long里捞出带TRIGGER关键字的事件再分析 -
SHOW INDEX FROM users看不出隐式转换,必须人工核对字段类型是否一致 - 避免在触发器里调用自定义函数,尤其含SQL的函数;
DETERMINISTIC函数也慎用,MySQL有时误判开销
递归触发会让CPU翻倍甚至飙到300%+
MySQL默认允许嵌套触发,A表INSERT触发B表UPDATE,B表UPDATE又触发C表INSERT……链式反应下,一个简单INSERT可能实际执行几十次查询。CPU不是匀速上升,而是阶梯式暴涨。
- 查当前递归深度:
SELECT @@max_sp_recursion_depth;值为0表示不限制(最危险) - 临时禁用递归(会话级):
SET max_sp_recursion_depth = 1 -
SHOW PROCESSLIST里info字段显示正在跑的触发器语句,再结合INFORMATION_SCHEMA.TRIGGERS反查定义
AFTER INSERT + FOR EACH ROW 是批量场景下的CPU杀手
批量插入INSERT INTO t VALUES (),(),()时,FOR EACH ROW会让触发器逐行执行N次。每次都要重跑一遍逻辑,CPU被反复压榨,而不是并行处理。
- 删掉触发器里的
SELECT ... FROM big_table WHERE ...,改用应用层查好ID后传入 - 用
NEW.column_name代替子查询,比如别写(SELECT status FROM config WHERE key = 'feature'),直接把配置值作为参数传进来 - 业务允许时,用单条
UPDATE ... CASE WHEN替代多个触发器更新,减少执行次数
真正难处理的从来不是“要不要用触发器”,而是“有没有把计算逻辑推到应用层之后再回写”——这点在监控图表里看不出来,但上线后CPU突然拉满,十有八九是触发器里藏着没拆出来的重型计算。

















