Почему растет журнал транзакций MS SQL после плана обслуживания и как это исправить?

Системный администратор IT и автоматизация бизнеса
← На главную

Многие администраторы при настройке связки 1С и MS SQL Server сталкиваются с классической проблемой: база данных весит относительно немного (например, 20 ГБ), а журнал транзакций разрастается до огромных размеров (14 ГБ и более) и стремительно поглощает свободное место на диске. При этом база переведена в режим полной модели восстановления (Full Recovery Model), а в регламентных заданиях настроено ежедневное обслуживание индексов и резервное копирование.

Проанализируем типичную ситуацию: каждую ночь в 02:00 выполняется проверка целостности, реорганизация индексов, обновление статистик и очистка кеша. С 08:00 утра до 18:00 вечера каждые полчаса выполняется резервное копирование журнала транзакций. Однако после ночного обслуживания файл журнала стремительно растет и не усекается, несмотря на заверения в документации Microsoft. Разберем по шагам, почему так происходит и как мы можем навсегда решить эту проблему.

Разберемся в терминах: Усечение против Сжатия

В первую очередь выясним причину терминологической путаницы. Очень часто администраторы путают два фундаментально разных процесса: усечение (Truncate) и сжатие (Shrink) файла журнала транзакций.

Усечение журнала (Truncate) — это логическая операция. Когда мы делаем бэкап журнала транзакций (ЖТ) в полной модели восстановления, SQL Server понимает, что зафиксированные транзакции надежно сохранены в резервной копии. Он помечает пространство, занятое этими транзакциями внутри файла ЖТ, как "свободное" и доступное для перезаписи новыми транзакциями. При этом физический размер файла на диске не уменьшается.

Сжатие файла (Shrink) — это физическая операция. Она реально отрезает пустое пространство с конца файла и возвращает его операционной системе.

Важно понимать: мы не должны регулярно сжимать журнал транзакций. Если база данных в процессе своей нормальной работы и ночного обслуживания требует файл размером 14 ГБ, значит, этот объем объективно необходим для размещения всех транзакций между бэкапами. Постоянное сжатие файла приведет к тому, что при следующей нагрузке SQL Server снова будет вынужден тратить ресурсы на физическое расширение файла на диске.

Проанализируем главную ошибку: Окно резервного копирования

Посмотрим внимательно на расписание из нашего сценария. Обслуживание (реорганизация индексов) запускается в 02:00 ночи. Реорганизация индексов — это полностью логируемая операция. SQL Server берет страницы данных, перекладывает их, упорядочивает и абсолютно каждое свое действие скрупулезно записывает в журнал транзакций.

Но когда выполняется первый бэкап журнала транзакций? Только в 08:00 утра!

Следовательно, с 02:00 до 08:00 все колоссальные объемы данных, сгенерированные реорганизацией индексов, накапливаются в файле ЖТ. Поскольку резервного копирования лога ночью нет, усечение не происходит. SQL Server не может перезаписать старые данные, поэтому он физически увеличивает размер файла, чтобы вместить новые транзакции. К утру файл раздувается до 14 ГБ, и только в 08:00 происходит бэкап, который усекает журнал логически, но физический размер (14 ГБ) остается навсегда.

Решение: Резервное копирование журнала транзакций должно выполняться круглосуточно, например, каждые 15–30 минут. Особенно важно сделать бэкап ЖТ непосредственно перед началом плана обслуживания и сразу же после его завершения. Это позволит SQL Server своевременно очищать место внутри файла и предотвратит его физическое разрастание.

Выясним причину задержки очистки журнала

Если вы настроили правильное расписание бэкапов, но файл всё равно отказывается усекаться (использовать внутреннее свободное место), давайте проведем диагностику. Мы можем точно узнать, что именно удерживает журнал от очистки, обратившись к системному представлению sys.databases.

Выполним следующий запрос:


SELECT name, log_reuse_wait_desc 
FROM sys.databases 
WHERE name = 'НазваниеВашейБазы1С';

Обратите внимание на колонку log_reuse_wait_desc. Если там указано LOG_BACKUP, значит, система просто ждет очередного бэкапа журнала. Если же там указано ACTIVE_TRANSACTION, значит, в базе "зависла" какая-то долгая транзакция (например, фоновое задание 1С зависло или пользователь начал проведение огромного документа и процесс оборвался). Пока эта транзакция не завершится (Commit) или не откатится (Rollback), SQL Server не сможет очистить журнал, даже если вы делаете бэкапы каждую минуту.

Проблема виртуальных лог-файлов (VLF) и производительность 1С

Рассмотрим еще один критичный аспект. Когда журнал транзакций регулярно переполняется и автоувеличивается мелкими шагами (например, по 10% или по 100 МБ), внутри физического файла создается огромное количество так называемых виртуальных лог-файлов (Virtual Log Files — VLF).

Наличие тысяч мелких VLF катастрофически сказывается на производительности 1С: замедляется старт базы данных, падают скорости операций записи, а самое страшное — восстановление базы из резервной копии (Recovery) может занять многие часы.

Давайте проверим количество VLF с помощью команды:

DBCC LOGINFO('НазваниеВашейБазы1С');

Количество строк в результате этого запроса — это количество VLF. Нормальное значение для базы 1С — от нескольких десятков до пары сотен. Если у вас их тысячи, проблему нужно срочно решать.

Алгоритм исправления:

  1. Дождитесь минимальной активности пользователей (вечер или выходной).
  2. Сделайте полный бэкап базы и бэкап журнала транзакций.
  3. Выполните разовое экстремальное сжатие файла ЖТ:
    
    USE НазваниеВашейБазы1С;
    GO
    DBCC SHRINKFILE (ИмяЛогическогоФайлаЖТ, 1);
    GO
    
  4. Сразу после этого вручную увеличьте файл до нужного размера (например, до 8 ГБ) одной командой. Это создаст оптимальное количество VLF:
    
    ALTER DATABASE НазваниеВашейБазы1С 
    MODIFY FILE (NAME = ИмяЛогическогоФайлаЖТ, SIZE = 8192MB);
    GO
    

Нужна ли реорганизация индексов каждый день на SSD?

Часто возникает вопрос: если база лежит на быстрых твердотельных накопителях (SSD NVMe в RAID 10), имеет ли смысл вообще бороться с фрагментацией индексов? SSD не имеет движущихся головок (как HDD), поэтому время поиска (seek time) у него стремится к нулю.

Посмотрим на это со стороны архитектуры MS SQL. SSD действительно нивелирует задержки физического чтения разбросанных блоков. Но логическая фрагментация никуда не исчезает! Сильная фрагментация не позволяет SQL Server эффективно использовать механизм упреждающего чтения (Read-Ahead). При построении тяжелых оборотно-сальдовых ведомостей или сложных отчетов в 1С SQL Server будет вынужден читать страницы данных по одной, вместо того чтобы считывать их крупными экстентами.

Таким образом, обслуживание индексов на SSD необходимо. Однако делать реорганизацию каждую ночь для всех индексов — это избыточно (overkill). Достаточно обслуживать индексы один раз в неделю, либо настроить интеллектуальный скрипт, который будет проверять процент фрагментации и перестраивать только те индексы, фрагментация которых превышает 30-40%.

Очистка кеша: скрытая угроза для производительности

В типовых планах обслуживания часто встречается пункт "Очистка кеша" (очистка процедурного кеша, DBCC FREEPROCCACHE). Проанализируем последствия этого действия для базы 1С.

Когда вы очищаете кеш планов запросов, SQL Server забывает, как оптимально выполнять запросы. Утром, когда пользователи массово начинают работать в 1С, на сервер обрушивается шквал новых запросов. SQL Server вынужден заново компилировать каждый запрос, строить планы выполнения и тратить на это огромные ресурсы процессора (CPU). Это вызывает сильные "тормоза" в первые часы работы.

Очистка кеша в ежедневном регламенте для 1С — вредная операция. Ее следует применять только точечно, при возникновении проблем с производительностью конкретных запросов ("отравление кеша"). Обязательно исключите этот шаг из ночного обслуживания.

Итоговые рекомендации и правильный план действий

Подведем итог и составим правильную стратегию для предотвращения роста журнала транзакций:

  1. Пересмотрите расписание бэкапов: Настройте резервное копирование журнала транзакций в режиме 24/7 (например, каждые 15 или 30 минут). Журнал транзакций должен бэкапиться и усекаться даже ночью.
  2. Добавьте принудительные бэкапы: Сделайте бэкап ЖТ за 5 минут до начала обслуживания индексов и сразу же после его окончания.
  3. Откажитесь от ежедневного обслуживания: Перенесите перестроение и реорганизацию индексов на выходные дни, либо используйте скрипты Олы Халленгрена (Ola Hallengren), которые интеллектуально обслуживают только фрагментированные таблицы.
  4. Уберите очистку кеша: Удалите шаг очистки процедурного кеша из ежедневного расписания, чтобы не перегружать процессор по утрам.
  5. Нормализуйте VLF: Проверьте количество виртуальных лог-файлов. Если их слишком много, выполните разовое сжатие файла лога и сразу же задайте ему адекватный стартовый размер. В настройках автоувеличения файла установите фиксированный шаг роста (например, по 512 МБ или 1 ГБ), отказавшись от роста в процентах.

Применяя эти практики, вы стабилизируете размер журнала транзакций, снизите нагрузку на дисковую подсистему и обеспечите предсказуемую и быструю работу сервера 1С:Предприятие для всех ваших пользователей.

← На главную