21.9.26

Delayed Durability в SQL Server

Автор: Paul Randal, Delayed Durability in SQL Server 2014

Одна из интересных новых возможностей SQL Server — отложенная устойчивость (delayed durability, доступна во всех редакциях), которая подробно описана в Books Online здесь.

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

Почему она даёт прирост пропускной способности?

Я собрал надуманную рабочую нагрузку с небольшой таблицей, где 50 параллельных клиентов обновляют одни и те же строки, а журнал базы данных находится на медленной подсистеме ввода-вывода. Вот график, показывающий мой тест:


На очевидной точке изменения — это место, где я включил отложенную устойчивость, принудительно применив её ко всем транзакциям. До изменения количество транзакций в секунду равно количеству сбросов журнала в секунду, поскольку каждая транзакция удерживает блокировки, блокирующие все остальные транзакции (я же говорил, что нагрузка надуманная). Так почему же произошёл огромный скачок транзакций в секунду, когда я принудительно включил отложенную устойчивость?

В обычных обстоятельствах, когда транзакция фиксируется, фиксация не завершается, пока блок журнала (см. этот пост в блоге для подробностей), содержащий запись журнала LOP_COMMIT_XACT для транзакции, не будет сброшен на диск и запись не будет подтверждена обратно в SQL Server как завершённая, обеспечивая устойчивость транзакции (буква D в свойствах ACID транзакции). Блокировки транзакции не могут быть сняты, пока сброс журнала не завершится.

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

При отложенной устойчивости фиксация транзакции продолжается без сброса блока журнала — следовательно, действие по обеспечению устойчивости транзакции откладывается. При отложенной устойчивости блоки журнала сбрасываются на диск только тогда, когда достигают своего максимального размера 60 КБ, или примерно каждую 1 мс, в зависимости от того, что наступит раньше. Это означает, что транзакции фиксируются гораздо быстрее, удерживают свои блокировки меньше времени, и поэтому количество транзакций в секунду сильно возрастает (для этой рабочей нагрузки). Вы также можете видеть, что количество сбросов журнала в секунду также сильно снизилось, поскольку раньше сбрасывалось множество крошечных блоков журнала, а затем стали сбрасываться только блоки максимального размера.

Примечание:

  • Я принудительно применял отложенную устойчивость ко всем транзакциям, но механизм позволяет делать выбор отложенной устойчивости и для каждой транзакции отдельно (см. Books Online для подробностей).
  • Есть немного больше в сбросе блоков журнала: при отложенной устойчивости блок журнала сбрасывается, когда заполняется, или если фиксируется транзакция без отложенной устойчивости, или если выполняется новая процедура sp_flush_log, или через 1 мс.

Мой хороший друг Aaron Bertrand из SQL Sentry написал длинную статью об отложенной устойчивости, в котором рассматривает её влияние на производительность немного глубже, так что я рекомендую ознакомиться и с его статьёй.

Так что это выглядит отлично, для правильного типа рабочей нагрузки. Но я готов поспорить, вы думаете:

В чём подвох?

Ваши транзакции не являются устойчивыми, когда фиксируются. Всё просто.

Теперь вы можете подумать, что если система даст сбой, вы потеряете максимум до 60 КБ журнала транзакций. Неправильно. Если последний блок журнала содержит запись журнала LOP_COMMIT_XACT для долго выполняющейся транзакции, когда система даст сбой, и этот блок журнала не на диске, вся эта транзакция откатится во время аварийного восстановления. Так что потенциал потери работы/данных больше, чем просто 60 КБ.

И это ещё не всё:

  • Резервные копии журнала не будут копировать этот не сброшенный блок журнала, поскольку его нет на диске, поэтому неустойчивые зафиксированные транзакции могут не содержаться в резервной копии журнала.
  • Неустойчивые транзакции, которые зафиксировались, также не защищены синхронным зеркалированием баз данных или синхронной группой доступности, поскольку они полагаются на сбросы блоков журнала (и передачу на зеркало/реплику).
  • Для критичных транзакций можно использовать sp_flush_log или вместо этого применять отложенную устойчивость для каждой транзакции отдельно.

Так что вопрос на миллион долларов:

Стоит ли включать отложенную устойчивость?

Зависит от обстоятельств. Готов ли ваш бизнес пойти на компромисс между пропускной способностью и устойчивостью? Даёт ли её включение прирост пропускной способности? Если да на оба вопроса — вперёд. Если нет хотя бы на один — не включайте. Это очень упрощённый способ думать об этом, но по сути всё сводится к этому.

Комментариев нет:

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