SQL Server和MySQL均无法直接获取触发器实际执行时间,因其被内联编译进宿主DML语句;需通过定位高开销DML、实时抓取长请求或手动埋点方式间接分析。

SQL Server 和 MySQL 都无法直接查到触发器的“实际执行时间”——这不是功能缺失,而是设计使然。 触发器不是独立运行的进程,它被内联编译进宿主 DML 语句(INSERT、UPDATE、DELETE),所有耗时都归属外层语句。想定位慢在哪,得绕过“查触发器”这个误区,转而查语句上下文和手动打点。
SQL Server:查不到触发器耗时,但能定位高开销 DML
别在 sys.dm_exec_trigger_stats 里找 cpu_time 或 elapsed_time 字段——它根本不存在。这个视图只提供累计调用次数(execution_count)和最后执行时间(last_execution_time),且仅缓存近期活跃的触发器(重启后未触发的不会出现)。
- 先确认触发器真被调用了:执行一条会激活它的 DML,再查
sys.dm_exec_trigger_stats - 用
sys.dm_exec_requests抓实时长请求:WHERE command IN ('INSERT', 'UPDATE', 'DELETE') AND total_elapsed_time > 500000(单位微秒,即 > 0.5 秒) - 通过
sql_handle提取完整 SQL,看操作的表是否挂了触发器;若logical_reads高但cpu_time低,大概率是触发器里做了没索引的JOIN或全表扫描
MySQL:必须手动埋点,否则耗时完全不可见
SHOW PROFILES 和慢查询日志(slow_query_log)对触发器内部逻辑无效——它们只记录外层语句耗时。想拿到真实数据,唯一可靠方式是在触发器代码里插时间戳。
- 在触发器开头和结尾各写一条:
INSERT INTO debug_log (event, ts) VALUES ('before_update', NOW(6))和INSERT INTO debug_log (event, ts) VALUES ('after_update', NOW(6)) - 禁用
autocommit时,触发器与主语句共用事务 ID,INFORMATION_SCHEMA.INNODB_TRX查不到触发器单独事务,别指望靠它捞执行栈 - 避免用
SLEEP()或USER()调试——可能被优化掉,或引发锁等待
MySQL 查触发器定义和存在性:用对命令才不漏信息
想确认触发器是否存在、内容是否正确,不能只靠 SHOW TRIGGERS ——它不支持按名称精确过滤,也不显示完整 SQL 定义。
- 查当前库所有触发器:
SHOW TRIGGERS \G(加\G格式更清晰) - 查指定触发器完整定义:
SHOW CREATE TRIGGER trigger_name - 查某库全部触发器详情(含事件、时机、SQL):
SELECT TRIGGER_NAME, EVENT_MANIPULATION, ACTION_TIMING, ACTION_STATEMENT FROM INFORMATION_SCHEMA.TRIGGERS WHERE TRIGGER_SCHEMA = 'your_db_name'
真正难的不是“怎么查”,而是意识到触发器耗时永远依附于 DML 语句——它的性能问题本质是语句设计问题。埋点、抓慢语句、检查触发器内是否查同表或大表,这三步漏掉任何一环,监控就形同虚设。

















