SQL Server 線上事故 90% 源自查詢問題,癥狀集中於 CPU 持續飆高 與 阻塞/死鎖。建立標準化排查腳本,將 MTTR (平均修復時間) 從小時級壓縮至分鐘級。
WITH HighCpuSessions AS (
SELECT session_id, cpu_time, total_elapsed_time,
sql_handle, statement_start_offset, statement_end_offset
FROM sys.dm_exec_requests
WHERE cpu_time > 5000 -- 超過 5 秒 CPU 積累
AND status IN ('running','runnable','suspended')
)
SELECT
H.session_id,
H.cpu_time,
H.total_elapsed_time,
DB_NAME(DB_ID()) AS CurrentDB,
SUBSTRING(ST.text,
(H.statement_start_offset/2)+1,
CASE WHEN H.statement_end_offset = -1 THEN DATALENGTH(ST.text)
ELSE (H.statement_end_offset - H.statement_start_offset)/2 + 1 END
) AS CurrentStatement,
ST.text AS FullBatchText
FROM HighCpuSessions H
CROSS APPLY sys.dm_exec_sql_text(H.sql_handle) ST
ORDER BY H.cpu_time DESC;
Table Scan、Index Scan (非覆蓋)、Key Lookup (大量)、Sort (溢寫 Tempdb)、Parallelism (不平衡/過度)。SET STATISTICS IO, TIME ON 實際 I/O 與時間。UPDATE STATISTICS TableName WITH FULLSCAN。OPTION (MAXDOP 1) 或實例層級降低平行度。WITH BlockingChain AS (
SELECT
r.session_id AS Spid,
r.blocking_session_id AS BlockedBy,
r.wait_type,
r.wait_time,
r.wait_resource,
r.cpu_time,
r.total_elapsed_time,
r.sql_handle
FROM sys.dm_exec_requests r
WHERE r.blocking_session_id > 0
OR r.session_id IN (SELECT blocking_session_id FROM sys.dm_exec_requests WHERE blocking_session_id > 0)
)
SELECT
B.Spid,
B.BlockedBy,
B.wait_type,
B.wait_resource,
SUBSTRING(ST.text, (B.statement_start_offset/2)+1,
CASE WHEN B.statement_end_offset=-1 THEN DATALENGTH(ST.text)
ELSE (B.statement_end_offset-B.statement_start_offset)/2+1 END) AS CurrentStmt,
ST.text AS FullBatch
FROM BlockingChain B
CROSS APPLY sys.dm_exec_sql_text(B.sql_handle) ST
ORDER BY B.BlockedBy, B.Spid;
EXEC sp_who2 'active'; -- 快速概覽 CPU、DiskIO、LastBatch、ProgramName EXEC sp_lock; -- 鎖資源詳細 (ObjId, IndId, Type, Resource, Mode, Status) -- 鎖資源對應物件 SELECT OBJECT_NAME(ObjId) AS ObjectName, * FROM ##sp_lock_result; -- 需先 INSERT EXEC -- 關鍵:DBCC INPUTBUFFER 看最後一條客戶端指令 DBCC INPUTBUFFER(52); -- SPID
system_health Extended Events 預設擷取 xml_deadlock_report。SELECT CAST(target_data AS XML) FROM sys.dm_xe_session_targets ...。DBCC TRACEON(1222, -1) 寫入錯誤日誌 (舊版)。KILL (業務確認後)。READ COMMITTED SNAPSHOT (RCSI) / SNAPSHOT 減少讀寫阻塞。| 目的 | 查詢 |
|---|---|
| 等待統計 | SELECT * FROM sys.dm_os_wait_stats ORDER BY wait_time_ms DESC; |
| 索引使用率 | SELECT * FROM sys.dm_db_index_usage_stats WHERE database_id = DB_ID(); |
| 缺失索引建議 | SELECT * FROM sys.dm_db_missing_index_details WHERE database_id = DB_ID(); |
| 查詢計畫快取 | SELECT TOP 50 qs.total_worker_time/qs.execution_count AS AvgCPU, qt.text FROM sys.dm_exec_query_stats qs CROSS APPLY sys.dm_exec_sql_text(qs.sql_handle) qt ORDER BY AvgCPU DESC; |
| Tempdb 空間耗用 | SELECT * FROM sys.dm_db_file_space_usage WHERE database_id = 2; |
將上述腳本封裝為 「CPU 排查包」 與 「阻塞排查包」 兩組預存程序,納入 DBA 日常巡檢與值班交接文件。事故發生時,依序執行 → 定位陳述式 → 分析計畫 → 快速緩解 → 根因修復 (索引/改寫/架構調整) → 複盤沉澱。工具標準化是降低 MTTR 的關鍵。