危害分析
- 阻塞其他事務 (鎖持有不釋放)
- 導致事務日誌無法截斷,磁碟暴漲
- 引發鎖升級、死鎖、連接池耗盡
核心監控查詢
-- 1. 活躍事務概覽
SELECT
at.transaction_id,
at.transaction_begin_time,
DATEDIFF(second, at.transaction_begin_time, GETDATE()) AS duration_sec,
at.transaction_type,
at.transaction_state,
s.session_id,
s.login_name,
s.host_name,
s.program_name,
t.text AS last_sql
FROM sys.dm_tran_active_transactions at
JOIN sys.dm_tran_session_transactions st ON at.transaction_id = st.transaction_id
JOIN sys.dm_exec_sessions s ON st.session_id = s.session_id
CROSS APPLY sys.dm_exec_sql_text(s.most_recent_sql_handle) t
WHERE at.transaction_type <> 2 -- 排除系統事務
ORDER BY at.transaction_begin_time;
-- 2. 長事務告警 (超過 60 秒)
SELECT * FROM (
-- 上述查詢
) t WHERE duration_sec > 60;
-- 3. 事務持有的鎖詳情
SELECT
tl.resource_type,
tl.resource_database_id,
tl.resource_associated_entity_id,
tl.request_mode,
tl.request_status,
OBJECT_NAME(tl.resource_associated_entity_id) AS object_name
FROM sys.dm_tran_locks tl
JOIN sys.dm_tran_active_transactions at ON tl.request_owner_id = at.transaction_id
WHERE at.transaction_begin_time < DATEADD(minute, -5, GETDATE());
自動化監控作業
-- SQL Agent Job 步驟
IF EXISTS (
SELECT 1 FROM sys.dm_tran_active_transactions at
JOIN sys.dm_tran_session_transactions st ON at.transaction_id = st.transaction_id
WHERE at.transaction_begin_time < DATEADD(minute, -10, GETDATE())
AND at.transaction_type <> 2
)
BEGIN
-- 發送郵件告警
EXEC msdb.dbo.sp_send_dbmail
@profile_name = 'DBA_Alerts',
@recipients = 'dba@company.com',
@subject = 'SQL Server 長事務告警',
@body = '檢測到超過 10 分鐘未提交事務,請立即處理。',
@query = '上述監控查詢',
@attach_query_result_as_file = 1;
END
常見成因與對策
| 成因 | 特徵 | 解決方案 |
| 應用異常拋出未回滾 | 事務狀態 2 (活躍)、無活躍請求 | 代碼加 try-catch-finally 確保回滾,連接池啟用驗證查詢 |
| 長時間運行的批次作業 | 事務狀態 2、有活躍請求 | 拆分小批次提交、使用批次框架 (SSIS/ETL)、避免業務高峰期 |
| 死鎖受害者未正確處理 | 事務被選為受害者但應用未重試 | 應用層實現死鎖重試邏輯 (指數退避) |
| 分佈式事務 (MSDTC) 卡頓 | 事務類型 3/4、狀態 4 (準備) | 檢查 MSDTC 服務、網絡延遲、協調器日誌 |
緊急處理流程
- 確認事務 ID (transaction_id)
- 評估業務影響:
SELECT * FROM sys.dm_exec_requests WHERE transaction_id = ?
- 若確認可終止:
KILL session_id (將觸發回滾,耗時與事務已做工作量成正比)
- 監控回滾進度:
KILL session_id WITH STATUSONLY
- 事後複盤:補全事務邊界、增加超時機制、完善監控