Почему сильно растет журнал транзакций MS SQL и как уменьшить файл LDF

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

При сопровождении баз данных 1С:Предприятия под управлением Microsoft SQL Server администраторы нередко сталкиваются с ситуацией, когда файл журнала транзакций (с расширением .ldf) разрастается до сотен гигабайт и полностью исчерпывает свободное дисковое пространство. При этом регулярные бэкапы лога и команды сжатия (Shrink) могут не давать желаемого эффекта. Разберем по шагам, почему возникает эта проблема, как выявить истинную причину блокировки очистки лога и как корректно настроить обслуживание базы данных.

Диагностика: выясняем причину задержки усечения журнала

В модели восстановления FULL (полная модель) журнал транзакций очищается только после создания резервной копии лога. Однако если файл продолжает непрерывно расти, значит, SQL Server не может повторно использовать освободившееся пространство. Проанализируем системное состояние базы с помощью простого запроса:


SELECT name, recovery_model_desc, log_reuse_wait_desc 
FROM sys.databases 
WHERE name = 'Имя_Вашей_Базы';

Посмотрим на значение в колонке log_reuse_wait_desc. Именно оно указывает на источник проблемы:

  1. ACTIVE_TRANSACTION — в базе присутствует незавершенная или зависшая транзакция. Пока она активна, СУБД обязана хранить все изменения начиная с момента ее старта, что блокирует усечение лога.
  2. LOG_BACKUP — системе требуется резервная копия журнала транзакций. Проверьте расписание регламентного бэкапа лога.
  3. REPLICATION или CHANGE_DATA_CAPTURE — включенные механизмы репликации или системы отслеживания изменений не успевают считывать данные.
  4. CHECKPOINT — контрольная точка еще не зафиксирована (часто встречается в модели SIMPLE).

Поиск зависшей транзакции и связь сессии SQL с пользователем 1С

Если диагностика показала наличие активной транзакции, выполним команду проверки открытых транзакций:

DBCC OPENTRAN;

Эта команда возвратит идентификатор сессии (SPID) и время запуска самой старой активной транзакции. Также детальные сведения можно получить через динамические административные представления:


SELECT 
    r.session_id,
    s.login_name,
    s.host_name,
    r.start_time,
    r.status,
    t.text
FROM sys.dm_exec_requests r
JOIN sys.dm_exec_sessions s ON r.session_id = s.session_id
CROSS APPLY sys.dm_exec_sql_text(r.sql_handle) t;

Выясним, как связать полученный идентификатор session_id с конкретным сеансом 1С, чтобы безопасно завершить зависшую операцию. Откроем утилиту «Консоль кластера серверов 1С:Предприятия», перейдем в ветку нужной информационной базы и откроем список «Соединения». В колонке «Номер соединения СУБД» (или «Идентификатор соединения СУБД») найдем число, в точности совпадающее с нашим session_id. Завершим проблемный сеанс штатно со стороны сервера 1С, чтобы не повредить кэш и корректно освободить блокировки.

Частыми виновниками долгих транзакций в 1С являются:

  1. Ошибки разработки: вызов модальных окон или вопросов пользователю внутри конструкции НачатьТранзакцию(). Пока диалог открыт на экране пользователя, транзакция висит и держит весь журнал.
  2. Массовая обработка больших объемов данных (перепроведение документов за несколько лет, загрузка справочников) без периодической фиксации порциями.
  3. Переполненные таблицы регистрации изменений планов обмена, если узлы обмена давно не синхронизировались.

Для предотвращения зависания пользовательских подключений настроим в консоли кластера 1С свойства информационной базы: установим параметры «Время засыпания пассивного сеанса» и «Время завершения спящего сеанса».

Ошибки в планах обслуживания: разрушительный цикл Reorganize и Shrink

Рассмотрим распространенную ошибку архитектуры обслуживания базы, когда ежедневно запускаются подряд Reorganize Index и Shrink Database. Такой регламент порождает замкнутый круг:

  1. Операция реорганизации индексов (REORGANIZE) полностью построчно протоколируется в транзакционном журнале. Это генерирует гигантский объем записей и заставляет файл .ldf расти лавинообразно.
  2. Последующая операция Shrink Database принудительно переносит страницы данных с конца файла в начало, чтобы освободить место. При этом перемещении физический порядок страниц нарушается, что приводит к фрагментации индексов практически до 100%.
  3. На следующий день план обслуживания вновь видит фрагментированные индексы и снова запускает тяжелую реорганизацию, генерируя новые гигабайты логов.

Исключим операцию Shrink Database из регулярных планов обслуживания. Сжатие файлов базы данных допустимо исключительно как разовая ручная операция после глобальных чисток или переноса массивов информации.

Опасность смены модели восстановления на лету

Иногда системные администраторы пытаются перед ночным обслуживанием перевести базу в простую модель восстановления (SET RECOVERY SIMPLE), а после переиндексации вернуть ее в FULL. Проанализируем последствия такого шага: в момент переключения в простую модель цепочка бэкапов журнала транзакций безвозвратно прерывается. Когда база возвращается в режим FULL, регулярные бэкапы лога не смогут очищать журнал до тех пор, пока не будет снят полный бэкап базы данных (Full Backup). До этого момента лог продолжит расти без возможности усечения.

Если требуется оптимизировать ночной рост лога при обслуживании индексов, заменим операцию REORGANIZE на полное перестроение (REBUILD) и временно переключим модель восстановления на неполное протоколирование (BULK_LOGGED):


ALTER DATABASE [Имя_Базы] SET RECOVERY BULK_LOGGED;
-- Выполняем перестроение индексов: ALTER INDEX ... REBUILD
ALTER DATABASE [Имя_Базы] SET RECOVERY FULL;

В режиме BULK_LOGGED операция REBUILD протоколируется минимально, объем журнала не увеличивается лавинообразно, а цепочка резервных копий журнала сохраняется целостной.

Фрагментация виртуальных файлов журнала (VLF) и правильная настройка авторасширения

Каждый файл журнала транзакций состоит из множества виртуальных файлов — VLF (Virtual Log Files). Если журнал постоянно растет мелкими порциями и часто сжимается, количество VLF может превысить несколько тысяч. Это приводит к сильным задержкам при фиксации транзакций и замедляет подъем базы при старте службы. Проверим структуру лога командой:

DBCC LOGINFO;

Количество строк в результате запроса показывает число VLF. Оптимальное количество должно находиться в диапазоне от нескольких десятков до пары сотен. Чтобы исправить фрагментацию VLF и предотвратить дальнейший неконтролируемый рост, выполним правильную последовательность действий:

  1. Убедимся в отсутствии активных зависших транзакций и выполним резервное копирование журнала: BACKUP LOG [Имя_Базы] TO DISK = 'D:\Backup\log_backup.trn';
  2. Сожмем журнал транзакций до минимального технологического размера: DBCC SHRINKFILE (Имя_Логического_Файла_Лога, 1024);
  3. Вручную инициализируем файл журнала до прогнозируемого рабочего размера. Например, выделим сразу 20–30 ГБ крупными блоками по 4–8 ГБ. Это создаст структуру с оптимальным числом крупных VLF:
    
    ALTER DATABASE [Имя_Базы] 
    MODIFY FILE (NAME = Имя_Логического_Файла_Лога, SIZE = 20480MB);
    
  4. Настроим шаг авторасширения (Autogrowth). Откажемся от настроек по умолчанию (маленькие шаги или прирост в процентах). Установим фиксированный шаг расширения размером от 1024 МБ до 2048 МБ.
  5. Скорректируем периодичность плана резервного копирования журнала транзакций. Если при часовом интервале лог все еще переполняется, уменьшим интервал до 15–30 минут, распределяя нагрузку на дисковую подсистему и стабилизируя размер файла на постоянном предсказуемом уровне.
← На главную