多數 DBA 習慣用 sys.dm_exec_requests 的 wait_type 診斷阻塞,但並行查詢下該視圖嚴重失真。本文通過實驗證明:sys.dm_os_waiting_tasks 能精準揭露每個 Parallel Worker 的真實等待類型與阻塞鏈,是並行效能調優的核心工具。
-- Session 55:持有排他鎖不提交 BEGIN TRAN; UPDATE t1 SET b = GETDATE(); -- 保持開啟 -- Session 54:並行查詢 (強制並行) SELECT * FROM t1 INNER JOIN t2 ON t1.a = t2.a OPTION (QUERYTRACEON 8649);
測試版本:SQL Server 2012,雙核 4 邏輯 CPU (DOP=4)。
| 欄位 | 型別 | 含義 |
|---|---|---|
| waiting_task_address | varbinary(8) | 等待任務位址 |
| session_id | smallint | 工作階段 ID |
| exec_context_id | int | 執行上下文 ID (0=協調者, >0=並行 Worker) |
| wait_duration_ms | int | 累積等待毫秒數 |
| wait_type | nvarchar(60) | 等待類型名稱 |
| resource_address | varbinary(8) | 等待資源位址 |
| blocking_task_address | varbinary(8) | 持有資源的任務位址 |
| blocking_session_id | smallint | 阻塞會話 ID (-2/-3/-4 為特殊狀態) |
| blocking_exec_context_id | int | 阻塞任務的執行上下文 ID |

LCK_M_S:exec_context_id = 5,6,7,8 (4 個掃描 Worker) 等待 Session 55 的 RID 鎖。ridlock fileid=1 pageid=109 dbid=7 ... associatedObjectId=72057594038910976 經 DBCC PAGE 驗證屬於 t1 表。CXPACKET (Exchange Port 等待) 與協調者等待。


wait_type = CXPACKET (並行等待泛稱,非真因)。blocking_session_id = 0 (無阻塞者資訊)。task_address 指向協調者 Task,而非真正等待鎖的 Worker。結論: 並行查詢下,sys.dm_exec_requests 僅反映協調者狀態,**完全掩蓋真實資源等待 (鎖、I/O、Latch)**。串行查詢時兩視圖一致。
CXPACKET) 接收。-- 即時檢視所有使用者會話的真實等待
SELECT
wt.session_id, wt.exec_context_id, wt.wait_type, wt.wait_duration_ms,
wt.resource_description, wt.blocking_session_id, wt.blocking_exec_context_id,
t.task_address, t.parent_task_address, t.worker_address
FROM sys.dm_os_waiting_tasks wt
LEFT JOIN sys.dm_os_tasks t
ON wt.waiting_task_address = t.task_address
AND wt.exec_context_id = t.exec_context_id
WHERE wt.session_id > 50; -- 過濾系統會話
dm_os_waiting_tasks vs dm_exec_requests 並行差異。掌握 sys.dm_os_waiting_tasks,即擁有並行查詢的「X 光眼」。