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

撰寫安全的 SQL Server 擴充預存程序 (DLL):參考計數管理多載入、TLS 執行緒隔離失敗分析與最佳實務

     編輯:關於SqlServer

擴充預存程序 (XP) 以 DLL 形式載入 SQL Server 進程位址空間,共用進程記憶體、執行緒池,安全撰寫極具挑戰。

核心難題:多載入與全域狀態

  • DLL 載入進程後,全域/靜態變數僅初始化一次,後續 LoadLibrary 僅增參考計數。
  • 若不處理,第二次呼叫 Init 會重複配置記憶體 → 洩漏;第一次呼叫 Final 釋放資源 → 後續呼叫崩潰。

方案一:參考計數 (採用)

HINSTANCE hInst = NULL; int nRef = 0;
RETCODE xp_part_init(SRV_PROC* p) {
    if (nRef == 0) { hInst = LoadLibrary("part.dll"); /* 初始化 */ }
    ++nRef; return XP_NOERROR;
}
RETCODE xp_part_process(SRV_PROC* p) { /* 使用 hInst 內的函數 */ }
RETCODE xp_part_finalize(SRV_PROC* p) {
    if (--nRef == 0) { /* 清理 */ FreeLibrary(hInst); hInst = NULL; }
    return XP_NOERROR;
}
  • 解決多載入/多釋放平衡問題。
  • 程式碼簡潔,風險可控。

方案二:TLS (Thread Local Storage) —— 理論可行但實際失敗

  • 構想:每連線/使用者獨立 TLS 槽位,隔離初始化狀態。
  • 失敗原因:SQL Server 使用執行緒池,同一使用者的多次請求可能由不同執行緒服務,TLS 狀態無法跟隨使用者,導致初始化狀態錯亂。
  • 驗證:查詢分析器多次執行觀察到執行緒 ID 變化,確認執行緒池機制。

殘留風險與緩解

  • 參考計數方案無法隔離不同使用者:使用者 A 呼叫 Final 兩次會影響使用者 B。
  • 緩解:文件規範「每連線僅呼叫一次 Init/Final」,或在應用層連線池管理生命週期。
  • 生產環境建議:改用 CLR 整合 (SQL 2005+),享受 AppDomain 隔離、型別安全、記憶體管理優勢,淘汰非受控 XP。

安全撰寫檢查清單

  1. 參考計數管理全域資源生命週期。
  2. 所有輸入參數嚴格驗證長度、型別、編碼(防緩衝區溢位/注入)。
  3. 錯誤碼統一規範,srv_paraminfo/srv_paramsetoutput 回傳值必檢。
  4. 避免阻塞呼叫 (I/O、鎖、睡眠),必要時改用非同步模式。
  5. 編譯啟用 /GS (緩衝區安全)、/DYNAMICBASE (ASLR)、/NXCOMPAT (DEP)。
  6. 簽署強名稱組件,部署至受信任路徑。

總結

XP 開發屬「危險區」,參考計數解決多載入資源洩漏,但無法解決多使用者隔離。現代架構全面轉向 CLR 整合,以受控執行環境取代非受控 DLL,從根本消除進程穩定性與安全性隱憂。

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