擴展預存程序本質是 DLL,載入 SQL Server 進程空間後,LoadLibrary 僅增加引用計數,全域/靜態變數不會重新初始化。若忽略此特性,多次呼叫初始化函數會導致資源洩漏或狀態錯亂。
HINSTANCE hInst = NULL;
int nRef = 0;
SRVRETCODE xp_part_init(SRV_PROC* p) {
if (nRef == 0) {
hInst = LoadLibrary("part.dll");
// 取得 Init 函數指標並呼叫...
}
++nRef;
return XP_NOERROR;
}
SRVRETCODE xp_part_finalize(SRV_PROC* p) {
if (nRef == 0) return XP_NOERROR;
if (--nRef == 0) {
// 呼叫 Fin 釋放資源
FreeLibrary(hInst); hInst = NULL;
}
return XP_NOERROR;
}
嘗試用 TLS 隔離使用者狀態(每位使用者獨立初始化/清理)失敗,因 SQL Server 使用執行緒池,同一使用者的多次呼叫可能分派給不同執行緒,TLS 無法保證同一邏輯連線對應同一執行緒。
xp_part_init / xp_part_finalize,否則會造成狀態不一致。擴展預存程序運行於 SQL Server 核心進程,穩定性與安全性容錯極低。引用計數雖非完美,但在現有架構下是相對可控的資源管理模式;TLS 因執行緒池機制而失效,開發者務必謹記。