Sql-Server

SQL AlwaysOn 可用性組中的數據一致性

  • July 14, 2021

我有一個 SQL Server 2019 的 AlwaysOn 集群,其中包含一個處於同步模式的 3 個副本的可用性組。根據微軟文件

  1. 輔助副本強化日誌並向主副本返回確認。
  2. 在收到來自輔助副本的確認後,主副本完成送出處理並向客戶端發送確認消息。

本文更詳細地解釋了這一點:

  1. 在輔助副本中,日誌接收從主副本獲取日誌記錄並寫入日誌記憶體。在參與同步送出模式的每個輔助副本上重複此過程。
  2. 在每個從副本上,都存在重做執行緒,它將日誌記錄中提到的所有更改寫入數據頁和索引頁。它刷新日誌以強化輔助數據庫日誌。
  3. 如前所述,在同步數據送出中,主副本等待來自輔助副本的確認。在此階段,輔助副本發送確認事務強化已在輔助副本上完成。
  4. 一旦主副本收到來自輔助副本的確認,它就會向客戶端發送事務完成消息。

因此,如果我理解正確: 如果我通過主副本成功更新記錄,則此更新後的值應該立即可供查詢輔助副本的客戶端使用。

但是,當我對此進行測試時,這不起作用。我執行一個簡單的批處理文件,如下所示:

sqlcmd -E -S tcp:SQL-AG-Listener -d TestDB -Q "BEGIN TRANSACTION; UPDATE TestSyncTable SET CurrentTime='%currentTime%'; COMMIT TRANSACTION;"
sqlcmd -E -S tcp:SQL-Server01 -d TestDB -Q "SELECT * FROM TestSyncTable" -K ReadOnly
sqlcmd -E -S tcp:SQL-Server02 -d TestDB -Q "SELECT * FROM TestSyncTable" -K ReadOnly
sqlcmd -E -S tcp:SQL-Server03 -d TestDB -Q "SELECT * FROM TestSyncTable" -K ReadOnly

所以我CurrentTime通過主副本(託管 AG 偵聽器)更新該欄位,然後立即通過所有三個副本讀取它。每個sqlcmd命令都是一個單獨的客戶端程序,因此它打開了自己獨立的 TCP 連接。

然後我看到這樣的東西:

SQL-Server01: CurrentTime = 20:02:19.93
SQL-Server02: CurrentTime = 20:02:16.94
SQL-Server03: CurrentTime = 20:02:19.93

(重新格式化輸出以獲得更好的可讀性)

據我所見,主副本始終返回更新後的值。輔助節點也這樣做 - 但只是一些短暫的延遲。

所以問題是:**為什麼?**同步模式不應該保證讀操作的結果與寫操作的結果一致嗎?如果輔助副本僅在其重做執行緒更新數據頁面後才發送確認 - 那怎麼可能呢?

謝謝,穆修斯。

來自您在問題中引用的同一篇 SQL Shack 文章:

  1. 次要副本還包含一個重做執行緒,它獨立於 SQL Server Always on 中的日誌塊程序。重做執行緒從日誌記憶體中讀取日誌。重做執行緒的處理可能會有延遲,並且日誌記錄可能在日誌記憶體中不可用,因為它已經被硬化到磁碟。在這種情況下,重做執行緒從日誌磁碟中讀取日誌塊。

我讀到的意思是日誌強化過程不會使更改立即在輔助數據庫中可用,而是輔助數據庫上的重做執行緒需要首先處理它們。

引用自:https://serverfault.com/questions/1069568