Согласованность данных в группе доступности SQL AlwaysOn

У меня есть кластер AlwaysOn SQL Server 2019, содержащий группу доступности из трех реплик в синхронном режиме. Согласно документации Microsoft :

  1. Вторичная реплика укрепляет журнал и возвращает подтверждение первичной реплике.
  2. Получив подтверждение от вторичной реплики, первичная реплика завершает обработку фиксации и отправляет клиенту подтверждающее сообщение.

В этой статье более подробно объясняется, что:

  1. Во вторичной реплике функция получения журнала получает записи журнала из первичной реплики и записывает их в кэш журнала. Этот процесс повторяется для каждой вторичной реплики, участвующей в режиме синхронной фиксации.
  2. В каждой вторичной реплике существует поток Redo, который записывает все изменения, упомянутые в записях журнала, на страницу данных и страницу индекса. Он очищает журнал для усиления защиты в журнале вторичной базы данных.
  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

(Здесь переформатирован вывод для лучшей читаемости)

Насколько я видел, первичная реплика всегда возвращает обновленное значение. И вторичные тоже делают, но только с небольшой задержкой.

Итак, вопрос: почему? Разве синхронный режим не должен гарантировать, что результат операции чтения соответствует результату записи? Если Secondary реплика отправляет подтверждение только после того, как ее поток Redo обновит страницу данных — то как это может быть?

Спасибо, Муций.

1 ответ

Из той же статьи SQL Shack, которую вы цитировали в своем вопросе:

  1. Вторичная реплика также содержит поток повторного выполнения и не зависит от процесса блокировки журнала в SQL Server. Всегда включено. Потоки повтора считывают журналы из кэша журналов. Возможна задержка в обработке потоком повторного выполнения, а записи журнала могут быть недоступны в кэше журнала, поскольку он уже зафиксирован на диске. В этом случае поток повтора читает блоки журнала с диска журнала.

Я понимаю, что это означает, что процесс усиления безопасности журнала не делает изменения немедленно доступными в базе данных-получателе, а скорее, что поток повторения на вторичной базе данных должен сначала их обработать.

Другие вопросы по тегам