При эксплуатации клиент-серверной архитектуры 1С:Предприятие 8.3 на базе Microsoft SQL Server системные администраторы и разработчики нередко сталкиваются с ситуацией, когда файл журнала транзакций базы данных (.ldf) и системная база данных tempdb начинают лавинообразно увеличиваться в объеме. В критических случаях журнал транзакций разрастается до сотен гигабайт, полностью утилизирует свободное дисковое пространство и приводит к аварийной остановке СУБД. При этом основной файл базы данных (.mdf) практически не меняет свой объем. Разберем детально, почему это происходит, как правильно диагностировать первопричину и какие регламентные меры навсегда решают данную проблему.
Журнал транзакций .ldf фиксирует все операции по модификации данных (вставки, изменения, удаления, перестроение индексов), обеспечивая согласованность базы и возможность восстановления при сбоях. Проанализируем основные факторы, вызывающие его переполнение:
В модели Full (Полная) СУБД сохраняет все транзакции и не очищает неактивную часть лога автоматически даже после выполнения полного резервного копирования базы (.mdf). Единственный способ усечь неактивную часть журнала в полной модели — регулярно выполнять резервное копирование самого лога транзакций (BACKUP LOG). Если такое расписание не настроено, файл .ldf будет расти бесконечно до исчерпания диска.
В модели Simple (Простая) неактивная часть лога усекается автоматически после фиксации каждой транзакции во время контрольной точки (CHECKPOINT).
Даже если бэкап лога настроен или используется модель Simple, SQL Server не может усечь лог дальше позиции самой старой открытой в данный момент транзакции (Active Transaction). Если фоновое задание, сеанс пользователя или внешняя интеграция открыли явную транзакцию и не завершили ее, все последующие операции будут накапливаться в логе.
В современных конфигурациях 1С (в частности, 1С:Управление торговлей 11, 1С:ERP, 1С:Комплексная автоматизация) после обновления платформы или конфигурации запускаются фоновые процедуры отложенного обновления данных (БСП). Эти процедуры в пакетном режиме массово перезаписывают сотни тысяч документов и движений регистров, генерируя колоссальный трафик транзакций.
Полная реиндексация таблиц (ALTER INDEX ... REBUILD) целиком протоколируется в журнале транзакций. Если размер таблиц и индексов составляет более 100 ГБ, разовая ночная реиндексация может моментально сгенерировать эквивалентный объем логов.
Синхронный рост файла .ldf рабочей базы и файлов данных tempdb — это важнейший маркер, указывающий на версионирование строк или неоптимальные запросы:
Стандартом для высоконагруженных баз 1С является включенный уровень изоляции READ_COMMITTED_SNAPSHOT (RCSI). При включенном RCSI предыдущие версии изменяемых строк сохраняются в хранилище версий строк, которое физически расположено в tempdb. Если в базе 1С зависает длительная открытая транзакция, механизм очистки Version Store не может удалить старые версии строк, созданные после старта этой транзакции. В результате tempdb и лог рабочей базы раздуваются одновременно.
Неоптимальные запросы в коде 1С (отсутствие условий в параметрах виртуальных таблиц, массивные левые соединения подзапросов, временные таблицы без индексации) вызывают нехватку оперативной памяти, выделенной для плана выполнения, и СУБД сбрасывает промежуточные результаты во временные таблицы tempdb.
Выясним причину, удерживающую журнал транзакций от усечения. Для этого выполним в среде SSMS диагностический запрос:
SELECT
name AS DatabaseName,
recovery_model_desc AS RecoveryModel,
log_reuse_wait_desc AS LogReuseWaitReason
FROM sys.databases
WHERE name = 'Имя_Вашей_Базы';
Проанализируем возвращаемое значение в колонке log_reuse_wait_desc:
Full, но не настроено резервное копирование журнала транзакций.Simple ожидает прохождения очередной контрольной точки.Если запрос показал причину ACTIVE_TRANSACTION, найдем самую старую открытую транзакцию в базе:
DBCC OPENTRAN('Имя_Вашей_Базы');
Команда вернет идентификатор сессии (SPID) и точное время старта транзакции. По полученному SPID выясним детали сессии и выполняемый в данный момент текст запроса:
SELECT
r.session_id,
r.status,
r.start_time,
r.command,
s.login_name,
s.host_name,
s.program_name,
t.text AS SqlQueryText
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
WHERE r.session_id = НОМЕР_SPID;
Зная имя хоста (host_name) и имя программы (program_name), мы можем открыть консоль Администрирование серверов 1С:Предприятия, найти соответствующий сеанс, фоновое задание или соединение и при необходимости завершить его.
Если диск переполнен и СУБД перестала функционировать, необходимо выполнить экстренные шаги по освобождению дискового пространства.
Вариант 1. База работает в модели Full:
Выполним резервное копирование журнала транзакций (это переведет неактивные страницы лога в состояние, готовое к перезаписи), после чего выполним сжатие файла лога до разумного размера:
-- 1. Создаем бэкап лога
BACKUP LOG [Имя_Вашей_Базы]
TO DISK = N'D:\Backup\Log_Emergency.trn'
WITH NOFORMAT, NOINIT, COMPRESSION;
-- 2. Сжимаем файл лога (указываем логическое имя файла лога)
DBCC SHRINKFILE (N'Имя_Файла_Лога_log', 2048); -- Сжать до 2 ГБ
Вариант 2. База переводится в модель Simple:
Если предприятию не требуется восстановление данных с точностью до секунды (Point-in-Time Recovery), переведем базу в простую модель восстановления, которая автоматически поддерживает компактный размер лога:
ALTER DATABASE [Имя_Вашей_Базы] SET RECOVERY SIMPLE;
GO
CHECKPOINT;
GO
-- Сжимаем файл лога
DBCC SHRINKFILE (N'Имя_Файла_Лога_log', 1024); -- Сжать до 1 ГБ
GO
Если раздувание лога началось после обновления релиза или платформы, разберем действия на стороне 1С:
Чтобы исключить повторение аварийных ситуаций, применим комплексные настройки регламентного обслуживания и параметров базы данных:
Если используется модель восстановления Full, создадим регулярное задание в SQL Server Agent на создание резервной копии лога каждые 15–30 минут в течение рабочего дня. Это обеспечит постоянное усечение лога и предотвратит его разрастание.
Запретим процентное расширение файлов (Percent-based Autogrowth). Установим фиксированный шаг расширения: для файла .mdf — 1024 МБ, для файла .ldf — 512 МБ. Это снизит фрагментацию файлов на физическом носителе и исключит зависания при резком выделении места.
Исключим полную безусловную реиндексацию всех таблиц. Настроим адаптивные сценарии обслуживания (например, скрипты Олы Халленгрена), которые выполняют REORGANIZE при фрагментации от 10% до 30% и REBUILD только для сильно фрагментированных таблиц с фрагментацией выше 30%.
Настроим количество файлов данных базы tempdb в соответствии с числом логических ядер процессора (от 4 до 8 файлов одинакового исходного размера и шага расширения) и разместим tempdb на выделенном быстром SSD/NVMe массиве.