適用於:SQL Server
Azure SQL Database
Azure SQL 受控實例
本文說明 SQL Server 如何使用安全性快取來驗證主體用來存取安全性物件的許可權。
目標
Database Engine 會組織稱為安全性實體的階層式集合,並可透過許可權來加以保護。 最突出的安全性實體是伺服器和資料庫,但許可權也可以更精細地設定。 SQL Server 會藉由確保主體具有適當的權限,控制可保護物件上的動作。
下圖顯示一位使用者 Alice 擁有伺服器層級的登入,且在三個不同的資料庫中,各有一個不同的使用者對應至相同的登入。
若要優化驗證程式,SQL Server 會使用安全性快取。
沒有快取工作流程
當安全性快取無效時,SQL Server 會遵循沒有快取工作流程來驗證許可權。 本節描述沒有快取工作流程。
若要示範,請考慮下列查詢:
SELECT t1.Column1,
t2.Column1
FROM Schema1.Table1 AS t1
INNER JOIN Schema2.Table2 AS t2
ON t1.Column1 = t2.Column2;
當安全性快取無效時,服務會在解析查詢之前,先完成下列工作流程中所述的步驟。
對於 SQL Server,不使用安全性快取的任務包括:
- 連接到實例。
- 執行登入驗證。
- 建立安全性內容令牌和登入令牌。 下一節將說明這些令牌的詳細數據。
- 連線至 資料庫。
- 在資料庫內建立資料庫使用者令牌。
- 檢查資料庫角色的成員資格。 例如,db_datareader、db_datawriter或db_owner。
- 確認所有欄位的使用者許可權,例如,確認使用者在
t1.Column1和t2.Column1的許可權。 - 檢查所有數據表的用戶許可權,例如
table1和table2,以及Schema1和Schema2的架構許可權。 - 驗證資料庫許可權。
SQL Server 會針對使用者所屬的每一個角色重複執行此程序。 取得所有許可權後,伺服器會檢查以確保使用者在權限鏈中具備所有必要的授權,並且權限鏈中沒有任何拒絕。 許可權檢查完成之後,查詢執行就會開始。
如需詳細資訊,請檢閱 許可權檢查演算法的摘要。
為了簡化驗證,SQL Server 會使用安全性快取。
安全性快取定義
安全性快取會儲存與使用者或登入相關的許可權,這些許可權是針對資料庫或伺服器中各種可保護的對象。 其中一個優點是加速查詢執行。 在 SQL Server 執行查詢之前,它會檢查使用者是否有不同資料庫安全性實體的必要許可權,例如架構層級許可權、數據表層級許可權和數據行許可權。
安全性快取物件
為了讓在上一節中說明的工作流程更快,SQL Server 會在安全性快取中儲存許多不同的物件。 快取的項目包括:
| 代幣 | 說明 |
|---|---|
SecContextToken |
主體的伺服器層級安全性上下文會保留在這個結構中。 它包含使用者令牌的哈希表,並做為所有其他快取的起點或基底。 包含登入令牌、使用者令牌、稽核快取和 TokenPerm 快取的參考。 此外,它會做為伺服器層級登入的基底令牌。 |
LoginToken |
類似於安全上下文令牌。 包含伺服器層級主體的詳細資訊。 登入令牌包含各種元素,例如 SID、登入帳號、登入類型、登入名稱、isDisabled 狀態,以及伺服器固定角色的成員資格。 此外,它也包含伺服器層級的特殊角色,例如系統管理員和安全性系統管理員。 |
UserToken |
此結構與資料庫層級主體相關。 其中包含使用者名稱、資料庫角色、SID、預設語言、預設架構、標識碼、角色和名稱等詳細數據。 每個資料庫都有一個使用者令牌可供登入。 |
TokenPerm |
記錄 UserToken 或 SecContextToken 相關安全物件的所有權限。 |
TokenAudit |
鍵是可保護物件的類別和識別碼。 條目是一系列清單,其中包含物件上每個可稽核作業的稽核 ID。 伺服器稽核是以許可權檢查為基礎,詳細說明特定使用者在特定對象上擁有的每個可稽核作業。 |
TokenAccessResult |
此快取儲存個別查詢的許可檢查結果,每個查詢計劃各有一個條目。 這是最重要的且常用的快取,因為它是查詢執行期間檢查的第一件事。 為了防止臨時查詢淹沒快取,查詢必須執行三次後,它才會儲存查詢許可權檢查結果。 |
ObjectPerm |
這會記錄資料庫中所有用戶在資料庫中物件的所有許可權。 TokenPerm 和 ObjectPerm 之間的差異在於 TokenPerm 適用於特定使用者,而 ObjectPerm 則適用於資料庫中的所有使用者。 |
安全性快取存放區
Token會儲存在不同的快取存放區內。
| Microsoft Store | 說明 |
|---|---|
TokenAndPermUserStore |
一個大存放區,其中包含下列所有物件: - SecContextToken- LoginToken- UserToken- TokenPerm- TokenAudit |
SecCtxtACRUserStore |
存取檢查結果 (ACR) 存放區。 每個登入都有自己的個別安全性上下文使用者存放區。 |
ACRUserStore |
存取檢查結果存放區<unique id> - <db id>- <user id>每個使用者都有個別的 ACR 使用者存放區。 例如,在兩個不同資料庫中,每個資料庫有兩個登入和五個使用者,總共相當於兩 SecCtxtACRUserStore 和 10 個不同的 ACRUserStore。 |
ObjectPerm |
每個資料庫一個ObjPerm令牌。 資料庫內的所有不同安全性實體。 |
已知問題
本節說明安全性快取相關的問題。
安全快取失效
各種案例可以在資料庫或伺服器層級觸發安全性快取失效。 發生失效時,所有目前的快取項目都會失效。 所有未來的查詢和許可權檢查都會遵循完整的「無快取」工作流程,直到重新填入快取為止。 失效可能會大幅影響伺服器效能,特別是在高負載下,因為所有啟動的連線都需要重建快取的條目。 重複的快取失效可能會使這種影響變得更糟。 資料庫中的 master 失效會被視為全伺服器無效,因而影響實例上所有資料庫的快取。
SQL Server 2025 引進了只針對特定登入使快取失效的功能。 這表示當安全性快取記錄失效時,只有那些屬於受影響登入的記錄會受到影響。 例如,如果您將登入 L1 授與新的許可權,登入 L2 的令牌仍不會受到影響。
在初始步驟中,這項功能適用於 CREATE、ALTER 和 DROP 登入案例,以及個別登入的許可權變更。 群組登入持續遭遇伺服器層級的無效情況。
下表列出所有使安全性快取失效的安全性資料定義語言 (DDL) 動作。
| 行動 | 主旨 | Scope |
|---|---|---|
CREATE/ALTER/DROP |
APPLICATION ROLESYMMETRIC KEYASYMMETRIC KEYAUTHORIZATIONCERTIFICATEROLESCHEMAUSER |
指定的資料庫 |
DROP |
出現在 sys.all_objects中的任何物件,或資料庫或架構範圍安全性實體清單中所列的任何安全性實體。 | 指定的資料庫 |
GRANT/DENY/REVOKE |
資料庫或架構中包含的安全物件的任何許可權。 | 指定的資料庫 |
CREATE/ALTER/DROP |
LOGIN( SERVICE) MASTER KEY |
SQL Server 執行個體 |
ALTER |
DATABASE |
指定的資料庫 |
當 TokenAndPermUserStore 的大小成長時,查詢效能受到影響。
效能問題,例如高 CPU 使用量和記憶體耗用量增加,可能是由 TokenAndPermUserStore 快取中的過多專案所造成。 根據預設,SQL Server 只會在偵測到內部記憶體壓力時清除此快取中的項目。 不過,在具有大量 RAM 的伺服器上,內部記憶體壓力可能不會經常發生。 隨著快取成長,搜尋現有的項目來重複利用所需的時間會增加。 此快取由自旋鎖管理,一次只允許一個線程執行搜尋。 因此,此行為可能會導致查詢效能降低,且CPU使用量較高。
因應措施
SQL Server 提供兩個追蹤旗標 (TF),可用來設定 TokenAndPermUserStore 快取的配額。 預設情況下,沒有配額,這表示快取可以保存無限制數量的條目。
- TF 4618:將 TokenAndPermUserStore 中的項目數目限制為 1024。
- TF 4618 和 TF 4610:將 TokenAndPermUserStore 中的項目數目限制為 8192。 如果 TF 4618 的低輸入計數限制導致其他效能問題,建議一起使用追蹤旗標 4610 和 4618。 如需詳細資訊,請參閱 使用 DBCC TRACEON 設定追蹤旗標。
如需詳細資訊,您可以參閱 效能問題可能是由 TokenAndPermUserStore 快取中過多項目所引起的 - SQL Server
最佳做法
本節列出優化安全性工作流程的最佳做法。
非尖峰時段的使用者管理
由於安全性快取的高層級失效特性(資料庫/伺服器層級),請在伺服器負載低的非營業時段執行安全性 DDL。 如果安全性快取在繁重的工作負載期間發生無效,當安全性快取重新填入時,可能會對整個伺服器造成明顯的效能影響。
使用單一交易進行許可權修改
在相同交易內執行多個安全性數據定義語言 (DDL) 作業可能會大幅增加與其他作用中連線發生死結的機會。若要降低此風險,建議您避免在單一交易中執行多個安全性 DDL。 相反地,在不同的交易中執行安全性相關的 DDL 作業,以將鎖定爭用降至最低。