mysql触发器是否会影响并发性能_mysql并发影响分析

MySQL触发器会显著拖慢高并发写入,因其同步执行且属于事务一部分,5ms触发器即可抬升行锁平均时间、降低TPS;跨表操作、远程调用、同表写入易引发锁争

用或死锁;空触发器也有0.1–0.3ms固定开销。

触发器会显著拖慢高并发写入场景

MySQL 触发器在 INSERTUPDATEDELETE 执行期间同步运行,属于事务的一部分。这意味着:只要触发器逻辑没跑完,该行(甚至整个表,取决于隔离级别和锁策略)就无法被其他事务安全修改。在每秒数百次以上写入的业务中(如订单创建、日志上报),一个耗时 5ms 的触发器就能让 innodb_row_lock_time_avg 明显升高,进而拉低整体 TPS

触发器里的 SELECT 或远程调用是并发杀手

以下操作在触发器中尤其危险:

  • BEFORE INSERT 里执行 SELECT ... FROM other_table WHERE x = NEW.y —— 可能引发间隙锁或锁升级,阻塞其他插入
  • 调用 SLEEP()UUID()(部分版本)、或自定义函数(含外部 HTTP 请求)—— 直接延长事务持有时间
  • 对同一张表做 INSERT/UPDATE(比如自增统计表)—— 极易触发 Deadlock found when trying to get lock
DELIMITER $$
CREATE TRIGGER order_after_insert_log
AFTER INSERT ON orders
FOR EACH ROW
BEGIN
  -- ❌ 危险:跨表 UPDATE + 可能锁住 users 表的某一行
  UPDATE users SET last_order_time = NOW() WHERE id = NEW.user_id;
END$$
DELIMITER ;

替代方案比优化触发器更有效

多数“必须用触发器”的需求,其实有更低开销的选择:

  • 把计数、状态更新等逻辑移到应用层,在主事务提交后异步处理(例如发 MQ 消息)
  • INSERT ... ON DUPLICATE KEY UPDATE 替代 BEFORE INSERT 中的查重逻辑
  • 对审计类日志,改用 BINLOG 解析(如 Canal / Debezium),完全绕过事务链路
  • 真需要强一致性且逻辑简单?优先考虑生成列(GENERATED COLUMN)或检查约束(CHECK CONSTRAINT

监控触发器真实开销不能只看 slow log

slow_query_log 默认不记录触发器内部语句,容易误判。要定位瓶颈,必须开启:

  • performance_schema=ON + 启用 events_statements_history_long
  • performance_schema.events_statements_history_longEVENT_NAME 包含 trigger 的记录
  • 重点关注 LOCK_TIMEEXECUTION_ENGINE(InnoDB vs MyISAM 行为差异大)

一个常被忽略的事实:即使触发器体为空,每次触发仍带来约 0.1–0.3ms 的固定上下文切换开销。在 QPS 超 2000 的写入集群里,这已足够让 p99 延迟跳变。