После выхода SQL Server 2014 ходили разговоры об изменениях в количестве VLF, создаваемых при увеличении или автоувеличении журнала (далее буду говорить «автоувеличение», так как это самый распространённый сценарий). Я немного поэкспериментировал и решил, что разгадал изменение алгоритма. Оказалось, нет. В рассылке MVP вопрос вспыхнул с новой силой, и мы коллективно пришли к выводу, что алгоритм ведёт себя недетерминированно… иначе говоря, мы не понимали, что он делает. Я написал друзьям в CSS, которые изучили код (спасибо, Bob Ward и Suresh Kandoth!) и объяснили изменение.
Изменение весьма существенное: оно нацелено на то, чтобы многочисленные автоувеличения не создавали гигантские количества VLF. Это здорово, потому что слишком много VLF (зависит от размера журнала, но многие тысячи — это слишком много) способны вызвать целый ворох проблем с производительностью при резервном копировании, восстановлении, очистке журнала, репликации, восстановлении после сбоя, откатах и даже при обычных операциях DML.
До 2014 года алгоритм количества создаваемых VLF при создании, увеличении или автоувеличении журнала зависел от соответствующего размера:
- Менее 1 МБ — хитрый случай, не рассматриваем.
- До 64 МБ: 4 новых VLF, каждый примерно равен 1/4 размера увеличения.
- От 64 МБ до 1 ГБ: 8 новых VLF, каждый примерно равен 1/8 размера увеличения.
- Более 1 ГБ: 16 новых VLF, каждый примерно равен 1/16 размера увеличения.
Так, если вы создали журнал размером 1 ГБ, а затем он автоувеличивался кусками по 512 МБ до 200 ГБ, вы получили бы 8 + ((200 – 1) x 2 x 8) = 3192 VLF. (8 VLF при первоначальном создании, затем 200 – 1 = 199 ГБ прироста по 512 МБ за автоувеличение = 398 автоувеличений, каждое добавляет 8 VLF.)
В SQL Server 2014 алгоритм теперь таков:
- Размер увеличения меньше 1/8 текущего размера журнала?
- Да: создать 1 новый VLF, равный размеру увеличения.
- Нет: использовать прежнюю формулу.
Значит, в SQL Server 2014, если вы создали журнал в 1 ГБ и он автоувеличивается кусками по 512 МБ до 200 ГБ, получится:
- 8 VLF при первоначальном создании журнала;
- Все увеличения до достижения журналом 4,5 ГБ используют формулу, поэтому увеличения на отметках 1, 1,5, 2, 2,5, 3, 3,5, 4, 4,5 ГБ каждое добавит по 8 VLF = 56 VLF;
- Все увеличения свыше 4,5 ГБ будут создавать по одному VLF за увеличение = (200 – 4,5) x 2 = 391 VLF;
- Итого = 391 + 56 + 8 = 455 VLF.
455 — куда более разумное число VLF, чем 3192, и проблем с производительностью будет значительно меньше.
В комментариях спросили, влияет ли уровень совместимости? Нет — внутренние механизмы подсистемы хранения игнорируют уровень совместимости.
На мой взгляд, это отличное изменение, и я не вижу в нём недостатков (кроме того, что оно не было публично освещено при выпуске SQL Server 2014). CSS скоро опубликует обстоятельный пост на эту тему, но они не возражали, чтобы я как можно скорее рассказал детали, чтобы избежать путаницы.
Можно подумать, что это приведёт к очень большим VLF (например, вы зададите автоувеличение 4 ГБ при журнале в 100 ГБ) — и такое возможно. Ну и что? Очень большие VLF — проблема только тогда, когда они созданы изначально, а затем вы пытаетесь сжать журнал. Минимум в журнале может быть лишь два VLF, так что вы застрянете с двумя огромными VLF в начале журнала, а дальше — более мелкие после последующих увеличений. Это может мешать журналу «замыкаться по кругу» и избегать автоувеличения, но такой сценарий встречается куда реже, чем наличие слишком большого числа VLF. И это НЕ тот сценарий, который создаёт новый алгоритм. (К слову, эту проблему можно обойти, создав снимок базы данных и выполнив откат к нему: журнал при этом удаляется и создаётся заново размером 0,5 МБ с двумя крошечными VLF… это не то чтобы ошибкаособенность, присутствующая с 2005 года, но имейте в виду: при этом рвётся цепочка резервных копий журнала.)
Безусловно, в будущем по управлению VLF можно сделать ещё многое (например, исправить описанную выше проблему), но уже сейчас это большой шаг в верном направлении.

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