Sql-Server-2016

如果 ##certificate-based## SQL Server 登錄的 SID 在可用性組中的副本之間不匹配,這會是故障轉移的問題嗎?

  • March 5, 2022

我正在閱讀有關可用性組中副本之間伺服器級對象同步的混合消息。

據我了解,伺服器級對象必須保持同步(旁白:那為什麼預設情況下它不是 AG 的一部分?)。例如,如果輔助副本上不存在登錄名(由 SID 標識)(無論使用者名和密碼如何),並且系統故障轉移到該副本,則相應的主體將無法進行身份驗證。

一切都很好 - 保持這些對象同步是一項需要完成的任務。但是基於證書的登錄呢?我讀到這些僅供內部系統使用,因此如果需要,我希望數據庫引擎跨副本維護 SID。我有一個包含三個節點的案例;第三個是只讀的。我看到主節點的 SID 用於登錄,例如##MS_SQLAuthenticatorCertificate##在其他任何一個節點上都不存在。然而,在那些其他節點上,存在一個具有相同名稱和不同 SID 的登錄,但是這兩個節點之間的 SID 相同,即:

SQL01 (Primary) SID = ABC
SQL02 (Secondary) SID = DEF
SQL03 (Read-only) SID = DEF

這值得關注嗎?儘管這些登錄在某些副本之間的 SID 不匹配,故障轉移是否會起作用?

這值得關注嗎?儘管這些登錄在某些副本之間的 SID 不匹配,故障轉移是否會起作用?

由於以下事實,我認為這與故障轉移無關:

  • 故障轉移主要針對基於數據庫鏡像端點的使用者數據庫
  • 使用者定義的 LOGIN 或 SERVICE ACCOUNT 所需的 ENDPOINT 上的 CONNECT 權限(不適用於名為 like 的伺服器主體##%)。

正如您所提到的,從根本上說,SID 是數據庫級別之間Login的相關性。User由於伺服器級別元數據同步超出可用性組的範圍,我們必須在所有副本(SQL 實例)中保持伺服器級別登錄的 SID 相同,以便它與User數據庫輔助副本中的 SID 匹配。

當故障轉移發生時,應用程序連接沒有失敗,因為loginSID = userSID,最終應用程序在數據庫上獲得相同的權限。否則數據庫中的使用者將成為孤立使用者

以下幾點說明了為什麼我們不必關註名為的伺服器主體'##%'

  1. 這些是在 SQL Server 安裝期間創建的,我們無法控制這些來管理 SID
  2. sys.database_principals這些只是內部用途,意味著只存在於系統數據庫中,與使用者數據庫主體( ) 沒有任何關係
  3. 使用者數據庫連接沒有問題,因為任何應用程序通常與名為 like 的主體沒有任何關係,並且使用者數據庫中不存在 '##%'主體 ( )。##%
  4. 最後,我們的目標是在每個副本中匹配伺服器主體的 SID =**數據庫主體的 SID 。**對於名為 like 的主體,##%預設情況下並始終在副本中維護相同的 SID,您可以使用以下查詢進行驗證:
select name, sid from sys.server_principals where name like '##%'

select name, sid from master.sys.database_principals where name like '##%'
select name, sid from msdb.sys.database_principals where name like '##%'

據我了解,伺服器級對象必須保持同步(旁白:那為什麼預設情況下它不是 AG 的一部分?)。

您是對的,這是此處明確說明的可用性組的限制..,在這種情況下,包含的數據庫功能將是一種使用數據庫本身進行身份驗證的解決方案。

不僅登錄,還有伺服器級別的元數據方面需要根據需要在可用性組之外進行管理。

這裡有幾個概念需要理解。

首先,SQL Server 中登錄名和使用者的區別。登錄是伺服器級主體,用於向伺服器進行身份驗證並為伺服器級對象提供授權。使用者是用於為數據庫級對象提供授權的數據庫級主體。在包含數據庫使用者的特殊情況下,使用者也可以用於身份驗證。

授予登錄名訪問數據庫的方法是將登錄名映射到數據庫使用者。此映射是使用 SID 實現的。此連結很好地概述了 SQL Server 中的權限層次結構。

接下來,我們需要了解那些## 登錄是什麼。根據這篇文件文章,帶有 ## 前綴和後綴的登錄表示“僅用於內部系統”的特殊基於證書的登錄。SQL Server 將這些登錄名用於特定的內部功能,因此在用途和實用性上僅與創建它們的實例隔離。

現在,就可用性組而言,任何給定 AG 的副本狀態都不會影響特定登錄對 SQL Server 進行身份驗證的能力。可用性組僅控制哪個副本響應組中給定數據庫的請求。它控制副本之間的數據移動​​和只讀請求的路由(如果已配置)。

所以,你的觀點:

據我了解,伺服器級對象必須保持同步(旁白:那為什麼預設情況下它不是 AG 的一部分?)。例如,如果輔助副本上不存在登錄名(由 SID 標識)(無論使用者名和密碼如何),並且系統故障轉移到該副本,則相應的主體將無法進行身份驗證。

如果滿足以下條件,則登錄名在故障轉移後仍然能夠進行身份驗證:

  • 對於 SQL 身份驗證登錄,副本之間的使用者名和密碼匹配。
  • 或者,使用了 Windows 登錄並且登錄存在於每個副本上
  • 或者,對於基於證書的登錄,證書存在於 master 中,並且登錄存在於每個副本上

當您的 SID 不匹配並且您想要訪問數據庫時,就會出現問題。故障轉移後,任何不匹配的 SID 都會導致孤立的數據庫使用者。User 仍然存在,Login 仍然存在但映射消失了,因此 Login 對數據庫的授權現在被破壞了。

如果您的連接字元串指向 AG 偵聽器但指定了主數據庫,那麼即使 SID 不匹配,您的登錄仍然可以工作。當您嘗試更改數據庫上下文或查詢已破壞映射的 AG 聯接數據庫時,就會出現該問題。通常,會與所需的特定數據庫建立連接,因此問題表現為登錄失敗,但從技術上講,它是登錄發生後在數據庫中授權失敗。

對於您的## 登錄,這無關緊要,因為它們永遠不會用於訪問 AG 中的數據庫。同樣,它們僅用於 SQL Server 的內部系統程序。

這值得關注嗎?儘管這些登錄在某些副本之間的 SID 不匹配,故障轉移是否會起作用?

不,這無關緊要。內部系統登錄的不匹配 SID 對故障轉移的影響為零。其他登錄名不匹配的 SID 可能會產生影響,這就是正確同步這些登錄名至關重要的原因。

對於 Windows 登錄,使用 AD 中帳戶的 SID,因此在將 Windows 登錄或組添加到副本時將自動正確。對於 SQL 身份驗證登錄,您需要在主副本上創建登錄,然後提取這些登錄的 SID 和密碼雜湊,以在其他副本上使用匹配的 SID 和密碼創建它們。

為了簡化此管理任務,您可以使用dbatools 之類的工具,它具有 PowerShell cmdlet,用於將登錄名與 SID 和密碼同步。

引用自:https://dba.stackexchange.com/questions/248848