首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 數據庫知識 >  >> SQL Server 資料庫 >> 關於SqlServer

SQL Server 查看未釋放游標:sys.dm_exec_cursors 即時監控與長時間開啟游標排查

     編輯:關於SqlServer

游標若未正確 `CLOSE`/`DEALLOCATE` 會佔用記憶體、鎖定資源、導致連線洩漏。SQL Server 提供動態管理函數 sys.dm_exec_cursors 即時檢視所有開啟/已關閉未釋放的游標。本文示範模擬洩漏場景、查詢腳本與長時間游標排查實務。

模擬游標洩漏 (工作階段 1)

DECLARE Cursor_Test CURSOR FOR SELECT * FROM dbo.TEST;
OPEN Cursor_Test;
-- 故意不執行 CLOSE / DEALLOCATE

查詢所有開啟游標 (工作階段 2)

SELECT 
    session_id, 
    cursor_id, 
    name, 
    creation_time, 
    is_open
FROM sys.dm_exec_cursors(0)
WHERE is_open = 1;

關鍵欄位:

  • `session_id`:SPID,可關聯 `sys.dm_exec_sessions` 取得登入/主機/程式資訊。
  • `cursor_id`:游標唯一識別碼。
  • `name`:游標宣告名稱。
  • `creation_time`:建立時間,可算出存活時長。
  • `is_open`:1 = 開啟中,0 = 已關閉但未釋放 (DEALLOCATE 前)。

查詢開啟游標結果

查詢已關閉但未釋放游標

工作階段 1 執行 `CLOSE Cursor_Test;` (不 DEALLOCATE) → 再查 `is_open = 0` 即可見。

已關閉未釋放游標

進階:排查超過 1 小時的游標

SELECT 
    c.creation_time,
    c.cursor_id,
    c.name,
    c.session_id,
    s.login_name,
    c.is_open
FROM sys.dm_exec_cursors(0) AS c
JOIN sys.dm_exec_sessions AS s ON c.session_id = s.session_id
WHERE DATEDIFF(HOUR, c.creation_time, GETDATE()) > 1;

游標最佳實務檢查清單

  1. ✅ 盡量避免游標:集合導向 (Set-based) SQL 效能遠優於逐列游標。
  2. 2. ✅ 必須成對:`OPEN` → `FETCH` 迴路 → `CLOSE` → `DEALLOCATE`。 3. ✅ 使用 `LOCAL` 游標:`DECLARE cursor_name CURSOR LOCAL ...` 讓游標在批次/預存程序結束自動清理。 4. ✅ 加入 `TRY/CATCH` 確保異常路徑也能釋放:
    BEGIN TRY
         DECLARE c CURSOR LOCAL FOR ...; OPEN c; ... 
         END TRY
         BEGIN CATCH
             IF CURSOR_STATUS('global','c') >= 0 BEGIN CLOSE c; DEALLOCATE c; END
             THROW;
         END CATCH
    5. ✅ 定期巡檢:納入每日健康檢查腳本,警報 `is_open=1` 超過閾值 (如 30 分鐘) 的游標。

掌握 `sys.dm_exec_cursors` 即時可視化,配合 `LOCAL` 游標與 `TRY/CATCH` 保護,即可從根源杜絕游標洩漏風險。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved