我有一个 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
(重新格式化输出以获得更好的可读性)
据我所见,主副本始终返回更新后的值。辅助节点也这样做 - 但只是一些短暂的延迟。
所以问题是:为什么?同步模式不应该保证读操作的结果与写操作的结果一致吗?如果辅助副本仅在其重做线程更新数据页面后才发送确认 - 那怎么可能呢?
谢谢,穆修斯。