Sql-Server
SQL AlwaysOn 可用性組中的數據一致性
我有一個 SQL Server 2019 的 AlwaysOn 集群,其中包含一個處於同步模式的 3 個副本的可用性組。根據微軟文件:
- 輔助副本強化日誌並向主副本返回確認。
- 在收到來自輔助副本的確認後,主副本完成送出處理並向客戶端發送確認消息。
本文更詳細地解釋了這一點:
- 在輔助副本中,日誌接收從主副本獲取日誌記錄並寫入日誌記憶體。在參與同步送出模式的每個輔助副本上重複此過程。
- 在每個從副本上,都存在重做執行緒,它將日誌記錄中提到的所有更改寫入數據頁和索引頁。它刷新日誌以強化輔助數據庫日誌。
- 如前所述,在同步數據送出中,主副本等待來自輔助副本的確認。在此階段,輔助副本發送確認事務強化已在輔助副本上完成。
- 一旦主副本收到來自輔助副本的確認,它就會向客戶端發送事務完成消息。
因此,如果我理解正確: 如果我通過主副本成功更新記錄,則此更新後的值應該立即可供查詢輔助副本的客戶端使用。
但是,當我對此進行測試時,這不起作用。我執行一個簡單的批處理文件,如下所示:
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 文章:
- 次要副本還包含一個重做執行緒,它獨立於 SQL Server Always on 中的日誌塊程序。重做執行緒從日誌記憶體中讀取日誌。重做執行緒的處理可能會有延遲,並且日誌記錄可能在日誌記憶體中不可用,因為它已經被硬化到磁碟。在這種情況下,重做執行緒從日誌磁碟中讀取日誌塊。
我讀到的意思是日誌強化過程不會使更改立即在輔助數據庫中可用,而是輔助數據庫上的重做執行緒需要首先處理它們。