Рейтинг:1

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

флаг ng

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

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

эта статья вникает в подробности и поясняет, что:

  1. Во вторичной реплике Log Receive получает записи журнала из первичной реплики и записывает их в кэш журналов. Этот процесс повторяется для каждой вторичной реплики, участвующей в режиме синхронной фиксации.
  2. На каждой вторичной реплике существует поток Redo, который записывает все изменения, упомянутые в записях журнала, на страницу данных и страницу индекса. Он очищает журнал для защиты в журнале вторичной базы данных.
  3. Как указывалось ранее, при синхронной фиксации данных первичная реплика ожидает подтверждения от вторичной реплики. На этом этапе вторичная реплика отправляет подтверждение того, что усиление транзакции на вторичном сервере завершено.
  4. Как только первичная реплика получает подтверждение от вторичной реплики, она отправляет клиенту сообщение о завершении транзакции.

Итак, если я правильно понимаю: Если я успешно обновлю запись через Первичную реплику, это обновленное значение должно быть немедленно доступны для клиентов, запрашивающих вторичные реплики.

Однако, когда я проверяю это, это так не работает. Я запускаю простой пакетный файл, который выглядит так:

sqlcmd -E -S tcp:SQL-AG-Listener -d TestDB -Q "НАЧАТЬ ТРАНЗАКЦИЮ; ОБНОВИТЬ TestSyncTable SET CurrentTime='%currentTime%'; СОВЕРШИТЬ ТРАНЗАКЦИЮ;"
sqlcmd -E -S tcp:SQL-Server01 -d TestDB -Q "SELECT * FROM TestSyncTable" -K Только для чтения
sqlcmd -E -S tcp:SQL-Server02 -d TestDB -Q "SELECT * FROM TestSyncTable" -K Только для чтения
sqlcmd -E -S tcp:SQL-Server03 -d TestDB -Q "SELECT * FROM TestSyncTable" -K Только для чтения

Итак, я обновляю Текущее время поле через основную реплику (где размещается прослушиватель AG), а затем сразу считывает его через все три реплики. Каждый sqlcmd Команда — это отдельный клиентский процесс, поэтому он открывает собственное независимое TCP-соединение.

И тут я вижу что-то вроде этого:

SQL-Server01: текущее время = 20:02:19,93
SQL-Server02: текущее время = 20:02:16,94
SQL-Server03: текущее время = 20:02:19,93

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

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

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

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

Рейтинг:1
флаг cn

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

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

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

Cat Mucius avatar
флаг ng
Да, кажется, что статья № 6 в SQL Shack вводит в заблуждение. Процесс, который записывает изменения в саму базу данных, не зависит от процесса защиты журнала, а подтверждение отправляется на Первичную реплику вне зависимости от ее работы. Эта статья Microsoft также поддерживает это: https://docs.microsoft.com/en-us/previous-versions/sql/sql-server-2012/dn135338(v=sql.110)

Ответить или комментировать

Большинство людей не понимают, что склонность к познанию нового открывает путь к обучению и улучшает межличностные связи. В исследованиях Элисон, например, хотя люди могли точно вспомнить, сколько вопросов было задано в их разговорах, они не чувствовали интуитивно связи между вопросами и симпатиями. В четырех исследованиях, в которых участники сами участвовали в разговорах или читали стенограммы чужих разговоров, люди, как правило, не осознавали, что задаваемый вопрос повлияет — или повлиял — на уровень дружбы между собеседниками.