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

巧用 SQL Server 全域暫存表防止使用者重複登入:連線斷開自動清理機制

     編輯:關於SqlServer

Web 系統需限制同一帳號同時僅能單點登入。傳統在使用者表加 IsLoggedIn 欄位,異常斷電導致旗標未重置,造成使用者無法登入。利用 **全域暫存表 (##Table) 隨連線中斷自動清理** 特性,可完美解決此問題。

核心機制

  • 區域暫存表 (#Table):僅對建立連線可見,連線結束自動刪除,**不適合跨連線共享狀態**。
  • 全域暫存表 (##Table):跨所有連線可見,**建立連線結束且無其他連線參考時自動刪除**,天然適合「在線狀態」標記。

實作預存程序

CREATE PROCEDURE dbo.CheckUserLogin
    @UserID VARCHAR(20),
    @IsLoggedIn BIT OUTPUT
AS
BEGIN
    SET NOCOUNT ON;
    DECLARE @TableName NVARCHAR(50) = N'##Login_' + @UserID;
    DECLARE @SQL NVARCHAR(MAX);

    IF OBJECT_ID('tempdb..' + @TableName) IS NULL
    BEGIN
        -- 首次登入:建立全域暫存表標記在線
        SET @SQL = N'CREATE TABLE ' + @TableName + N' (UserID VARCHAR(20)); INSERT ' + @TableName + N' VALUES (@uid);';
        EXEC sp_executesql @SQL, N'@uid VARCHAR(20)', @UserID;
        SET @IsLoggedIn = 0;  -- 允許登入
    END
    ELSE
    BEGIN
        -- 已有表存在 → 該帳號正在線
        SET @IsLoggedIn = 1;  -- 拒絕登入
    END
END

應用程式呼叫流程

  1. 使用者提交帳號密碼。
  2. 呼叫 CheckUserLogin @UserID, @IsLoggedIn OUTPUT。
  3. @IsLoggedIn = 1 → 回傳「該帳號已在線,請先登出」。
  4. @IsLoggedIn = 0 → 驗證密碼、建立 Session、寫入登入日誌。
  5. 使用者正常登出或 Session 逾期 → 連線池釋放連線 → 全域暫存表自動刪除 → 下次可登入。
  6. 異常斷電/瀏覽器關閉 → 連線中斷 → 同樣觸發自動清理,**無孤立旗標問題**。

注意事項

  • 全域暫存表名稱長度 ≤ 116 字元 (含 ##),UserID 過長時需雜湊縮短。
  • 連線池重用可能延遲清理;若需即時釋放,登出時顯式 DROP TABLE ##Login_...。
  • 高併發下建表競爭極低 (同一帳號同秒登入機率極低);若極度在意,可用 sp_getapplock 序列化。

擴展:多伺服器叢集環境

單機方案無法跨節點共享狀態。叢集環境建議改用 **Redis Set (SETNX)** 或 **資料庫表 + 分散式鎖** 實現單點登入。

結語

全域暫存表「隨連線生命週期自動清理」的特性,以極簡代碼解決單機單點登入的異常殘留旗標難題,是輕量級 Web 系統的實用技巧。

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