SQL Server DELETE无法监控行级进度,只能判断执行状态与阻塞原因;应结合sys.dm_exec_requests查运行状态、DBCC OPENTRAN看事务起点、sys.dm_tran_locks定位锁冲突,并用sp_WhoIsActive替代sp_who2获取完整上下文。

SQL Server 的 DELETE 本身不暴露行级进度,percent_complete 对它永远是 0;你真正能监控的,是“它卡在哪”“是不是真在跑”,而不是“还剩多少行没删”。
查 sys.dm_exec_requests 看 DELETE 是否活着、卡在哪
这是第一反应该查的视图。它告诉你当前这个 DELETE 请求的状态,不是“删了多少”,而是“它现在算不算正常工作”。
-
command = 'DELETE'且status = 'running':说明它正在执行(但不等于快——可能正扫全表) -
status = 'suspended'且wait_type非空(比如LCK_M_U、PAGEIOLATCH_SH):它被锁或 I/O 卡住了,不是慢,是堵 -
last_wait_type和start_time结合看:如果同一wait_type持续十几分钟,基本可判定阻塞未解 -
session_id是后续所有排查的起点,必须记牢
用 DBCC OPENTRAN 判断事务起点是否异常
它不告诉你进度,但能帮你区分“刚启动就被堵”和“真删了 40 分钟还没完”。关键看事务 BEGIN 时间。
- 必须在目标数据库上下文里执行:
USE [YourDB]; DBCC OPENTRAN; - 输出中
Oldest active transaction行的SPID应与sys.dm_exec_requests.session_id匹配 - 如果
DBCC OPENTRAN显示事务始于 2 分钟前,但你看到它“跑了 45 分钟”,那它大概率从第 2 分钟起就suspended了 - 若返回
No active open transactions,说明事务已结束(提交或回滚),你看到的可能是残留连接或未释放会话
查 sys.dm_tran_locks 定位锁冲突源头
90% 的“长 DELETE”不动,根源是锁。这里能看出它锁了什么、等谁放、甚至谁在锁它。
- 先过滤:
WHERE request_session_id = @your_session_id - 重点看
resource_type:'KEY'多说明走索引逐行删;'OBJECT'或'PAGE'多可能已锁升级或扫描范围过大 - 找
request_status = 'WAIT'的记录,再根据resource_description(常含页号或键值)往上翻,找相同描述且request_status = 'GRANT'的行——那就是持锁者 - 若发现大量
KEY锁但resource_description分散(如不同hobt_id),说明没走覆盖索引,排序/定位开销大
别用 sp_who2,装个 sp_WhoIsActive
sp_who2 输出太简陋,缺 SQL 文本、缺等待资源细节、默认混入系统进程,容易漏掉关键线索。
-
sp_WhoIsActive默认输出包含:sql_text(能看到实际删的条件)、blocking_session_id(谁在堵它)、wait_info(带超时时间的完整等待链) - 安装只需运行作者官网提供的脚本,无副作用
- 常用调用:
EXEC sp_WhoIsActive @filter = @session_id, @filter_type = 'session'; - 它还能导出为 XML 或存表分析,适合持续盯梢
真正难的不是“怎么查”,而是把 sys.dm_exec_requests、DBCC OPENTRAN、sys.dm_tran_locks 三者的输出串起来读——比如看到 suspended + LCK_M_U,立刻去锁视图里找谁占着那个 KEY,再顺藤摸到持锁者的 SQL。这个闭环判断,比任何单点指标都管用。

















