如何排查SQL Server表的更新来源(作业/SSIS/触发器等)
我之前也碰到过这种摸不着头脑的情况——明明查到了更新语句,却不知道是谁在执行!给你分享几个我亲测有效的排查方法,一步步缩小范围:
排查SQL Server更新语句来源的实用思路
1. 扩展查询统计,抓执行上下文细节
你现有的查询可以加几个DMV,把会话和客户端信息拉出来,关键信息藏在这里:
SELECT deqs.sql_handle, deqs.plan_handle, deqs.last_execution_time, dest.text, des.session_id, des.login_name, des.host_name, des.program_name, -- 重点看这个!能直接区分执行源 des.status, dec.client_interface_name FROM sys.dm_exec_query_stats AS deqs CROSS APPLY sys.dm_exec_sql_text(deqs.sql_handle) AS dest JOIN sys.dm_exec_sessions des ON deqs.session_id = des.session_id JOIN sys.dm_exec_connections dec ON des.session_id = dec.session_id WHERE dest.text LIKE '%Update%' ORDER BY deqs.last_execution_time desc
这里的program_name是宝藏字段:
- 要是SQL Server Agent作业执行的,会显示类似
SQLAgent - TSQL JobStep (Job 0xXXXXXX... : Step X)的标识 - 若是SSIS包跑的,大概率能看到
DTExec.exe或者你的SSIS项目名称 - 如果是触发器触发的,这个字段会和触发它的父进程一致,咱们再用下面的方法确认
2. 排查触发器是否在干活
怀疑是触发器的话,有两个办法:
先查现有触发器的基本情况
SELECT OBJECT_NAME(parent_id) AS 关联表名, name AS 触发器名称, create_date, modify_date FROM sys.triggers WHERE parent_id = OBJECT_ID('你的目标表名') -- 替换成你的表名
临时加日志追踪(记得事后清理)
先建个日志表:
CREATE TABLE TriggerExecutionLog ( LogID INT IDENTITY(1,1) PRIMARY KEY, 执行时间 DATETIME DEFAULT GETDATE(), 触发器名称 NVARCHAR(128), 执行用户 NVARCHAR(128), 会话信息 NVARCHAR(MAX) )
然后修改触发器,插入日志:
ALTER TRIGGER [你的触发器名] ON [你的目标表名] AFTER UPDATE AS BEGIN INSERT INTO TriggerExecutionLog (触发器名称, 执行用户, 会话信息) VALUES (OBJECT_NAME(@@PROCID), SUSER_SNAME(), CONCAT('会话ID: ', @@SPID, ' 程序名: ', APP_NAME())) END
等更新发生后,查这个日志表就能实锤是不是触发器干的。
3. 检查SQL Server Agent作业
怀疑是Agent作业的话,直接查作业历史:
SELECT j.name AS 作业名称, js.step_name AS 步骤名称, jh.run_date AS 执行日期, jh.run_time AS 执行时间, CASE jh.run_status WHEN 0 THEN '失败' WHEN 1 THEN '成功' ELSE '其他' END AS 执行状态 FROM msdb.dbo.sysjobs j JOIN msdb.dbo.sysjobsteps js ON j.job_id = js.job_id JOIN msdb.dbo.sysjobhistory jh ON j.job_id = jh.job_id AND js.step_id = jh.step_id WHERE jh.run_date >= CONVERT(VARCHAR(8), GETDATE()-1, 112) -- 查最近1天的记录 AND js.command LIKE '%Update%' -- 筛选包含Update的作业步骤 ORDER BY jh.run_date DESC, jh.run_time DESC
也可以直接在SQL Server Agent的界面里,按执行时间排序,找最近跑过的作业,看步骤里有没有Update语句。
4. 用Extended Events实时追踪(最靠谱)
如果上面的方法都没找到,用Extended Events抓实时事件准没错:
创建一个针对sql_statement_completed事件的会话,筛选条件设为text_data LIKE '%Update 你的目标表名%',同时捕获session_id、program_name、login_name、client_app_name这些字段。更新发生时,就能直接拿到完整的执行上下文,一眼看穿来源。
内容的提问来源于stack exchange,提问作者user1603398
相关产品推荐
相关产品推荐

