Журнал транзакций базы 1С занял весь диск: как сжать LDF и не допустить повторного роста
Содержание
Чтобы уменьшить файл .ldf базы 1С в SQL Server, сначала освободите место внутри журнала транзакций, а потом сожмите сам файл командой DBCC SHRINKFILE. Освободить журнал можно двумя путями: перевести базу в модель восстановления SIMPLE или сделать резервную копию журнала (BACKUP LOG) и остаться в FULL.
Первый путь быстрее и подходит, если восстановление на произвольный момент времени вам не нужно, а хватает ежедневных полных копий. Второй выбирают, когда база важная и терять даже час работы нельзя. Сжатие само по себе без этих шагов почти ничего не даёт: файл не уменьшится, пока внутри лога висят неосвобождённые записи.
| Способ | Когда выбирать | Что теряете |
|---|---|---|
SIMPLE + сжатие | Небольшая фирма, полная копия раз в сутки устраивает | Восстановление на точку во времени |
BACKUP LOG + сжатие, остаётесь в FULL | Важная база, нужна точка восстановления внутри дня | Ничего, но нужен регламент копий лога |
| Отключить базу и удалить LDF | Никогда | Рискуете получить неоткрываемую базу |
Почему журнал транзакций базы 1С разрастается
SQL Server пишет в журнал каждое изменение данных: проведение документов, закрытие месяца , загрузку из банка, реструктуризацию при обновлении конфигурации. Место внутри журнала освобождается только при определённых условиях, и они зависят от модели восстановления.
Когда база 1С создаётся через консоль кластера или из окна запуска, SQL Server берёт параметры из системной базы model. У неё по умолчанию модель FULL. В итоге база работает в полной модели, а копии журнала никто не делает. Лог растёт без ограничений, пока не займёт диск.
Основные причины роста:
- 📈 модель
FULLилиBULK_LOGGEDбез регулярногоBACKUP LOG; - ⏳ долгая открытая транзакция: зависший сеанс, закрытие месяца на большой базе, обработка, которая меняет миллионы записей одной транзакцией;
- 🔧 обновление конфигурации с реструктуризацией крупных таблиц;
- 🧱 перестроение индексов в плане обслуживания: операция полностью журналируется в модели
FULL; - 🔁 репликация, зеркалирование или группы доступности, которые ещё не забрали записи из лога.
Если журнал уже в несколько раз больше файла данных .mdf, почти наверняка это первая причина: полная модель без копий журнала.
Как проверить, чем занят журнал и сколько в нём свободно
Не начинайте со сжатия. Сначала выясните, что держит лог, иначе команда отработает без результата.
Откройте SQL Server Management Studio, подключитесь к серверу и выполните запрос в окне New Query. Узнаём размер журнала и процент заполнения по всем базам:
DBCC SQLPERF(LOGSPACE);
В результате колонки Log Size (MB) и Log Space Used (%). Если файл занимает 80 ГБ, а заполнен на 3%, место внутри уже свободно и остаётся только сжать файл. Если заполнен на 95%, сначала нужно освободить журнал.
Теперь главный вопрос: что мешает освобождению. Подставьте имя своей базы:
SELECT name, recovery_model_desc, log_reuse_wait_desc
FROM sys.databases
WHERE name = N'buh_base';
Колонка log_reuse_wait_desc прямо называет причину:
| Значение | Что означает | Что делать |
|---|---|---|
NOTHING | Журнал ничем не удерживается | Можно сжимать |
LOG_BACKUP | Ждёт резервной копии журнала | BACKUP LOG или перевод в SIMPLE |
ACTIVE_TRANSACTION | Открыта долгая транзакция | Найти её через DBCC OPENTRAN |
CHECKPOINT | Не было контрольной точки | Выполнить CHECKPOINT |
REPLICATION, AVAILABILITY_REPLICA | Лог ждёт реплику | Разбираться с репликацией, не сжимать вслепую |
Логическое имя файла журнала понадобится для сжатия. Оно часто не совпадает с именем файла на диске:
USE [buh_base];
SELECT name, physical_name, size * 8 / 1024 AS size_mb
FROM sys.database_files
WHERE type_desc = N'LOG';
Колонка size хранится в страницах по 8 КБ, поэтому умножаем на 8 и делим на 1024, получаем мегабайты.
Быстрое решение: модель SIMPLE и сжатие файла LDF
Этот вариант освобождает диск за пару минут. Пользователей выгонять из 1С не нужно, сервер 1С останавливать тоже. Но в часы нагрузки сжатие идёт медленнее, поэтому лучше выбрать время, когда в базе мало работы.
Перед сменой модели сделайте полную резервную копию базы
средствами SQL Server. После перехода в SIMPLE цепочка копий журнала обрывается, и восстановить базу на момент внутри дня по старым копиям лога уже не получится.
Порядок действий:
- Сделайте полную копию базы: в SSMS правой кнопкой по базе,
Tasks → Back Up..., типFull. - Переведите базу в простую модель и выполните контрольную точку.
- Сожмите файл журнала до разумного размера.
- Проверьте результат через
DBCC SQLPERF(LOGSPACE).
Скрипт целиком (замените buh_base и buh_base_log на свои имена из запроса выше):
USE [master];
ALTER DATABASE [buh_base] SET RECOVERY SIMPLE;
GO
USE [buh_base];
CHECKPOINT;
GO
DBCC SHRINKFILE (N'buh_base_log', 1024);
GO
Число 1024 — целевой размер в мегабайтах. Не сжимайте журнал до 1 МБ: при первой же крупной операции он снова начнёт расти небольшими приращениями, и это замедлит работу 1С.
Сколько оставить, ориентируйтесь так: примерно 10–25% от размера файла данных, но не меньше 1 ГБ. Для базы на 40 ГБ это 4–10 ГБ.
В модели SIMPLE журнал тоже может вырасти, если идёт одна огромная транзакция. Например, закрытие года на крупной базе. Модель освобождает лог после контрольной точки, но не может освободить записи ещё открытой транзакции.
Через графический интерфейс то же делается так: свойства базы, страница Options, поле Recovery model = Simple. Затем правой кнопкой по базе Tasks → Shrink → Files, тип файла Log, режим Reorganize pages before releasing unused space с указанием целевого размера.
Сжатие журнала без смены модели восстановления
Если база должна остаться в FULL, освобождайте журнал резервной копией лога. После неё неактивная часть журнала становится доступной для повторного использования, и файл можно сжать.
BACKUP LOG [buh_base]
TO DISK = N'D:\Backup\buh_base_log.trn';
GO
USE [buh_base];
DBCC SHRINKFILE (N'buh_base_log', 4096);
GO
С первого раза файл часто уменьшается не до конца. Причина в том, что активная часть журнала находится в конце файла, а SQL Server отрезает только хвост. Сделайте ещё одну копию журнала и повторите сжатие. Обычно хватает двух-трёх циклов.
Если база была в SIMPLE и вы возвращаете её в FULL, сразу после переключения сделайте полную копию. Пока её нет, BACKUP LOG вернёт ошибку, а журнал будет вести себя как в простой модели.
Копию лога можно делать в файл NUL, чтобы просто освободить журнал без записи на диск. Работает, но этим вы ломаете цепочку копий так же, как переходом в SIMPLE. Если так делать, то честнее перейти в простую модель.
Регулярное резервное копирование журнала, чтобы LDF не рос снова
Сжатие — разовая мера. Если оставить полную модель без копий лога, через месяц-два диск закончится снова.
Выберите один вариант и закрепите его в регламенте:
- 🟢 Модель
SIMPLE+ полная копия каждую ночь. Самый простой режим для небольших баз. При сбое теряется работа с момента последней копии. - 🟡 Модель
FULL+ полная копия ночью + копия журнала каждые 15–60 минут. Можно восстановиться на любую минуту. Размер журнала держится в пределах объёма изменений за интервал. - 🔵 Дифференциальные копии в течение дня добавляют к любому из вариантов, когда база большая и полная копия идёт долго.
Пример: база 60 ГБ, за час пользователи генерируют около 300 МБ записей в журнал. При копии лога раз в 30 минут ему хватит 1–2 ГБ даже с запасом на закрытие месяца. Без копий те же 300 МБ в час дадут примерно 7 ГБ в сутки, около 200 ГБ за месяц.
Проверьте и настройку роста файла. Прирост в процентах для журнала плох: чем больше файл, тем крупнее каждый скачок. Поставьте фиксированный шаг:
ALTER DATABASE [buh_base]
MODIFY FILE (NAME = N'buh_base_log', FILEGROWTH = 512MB);
Слишком мелкий шаг (1 МБ, 10 МБ) тоже вреден. Журнал дробится на тысячи виртуальных сегментов (VLF), из-за этого медленнее идёт восстановление и запуск базы. Количество сегментов в SQL Server 2016 SP2 и новее смотрят так:
SELECT COUNT(*) AS vlf_count
FROM sys.dm_db_log_info(DB_ID(N'buh_base'));
Если сегментов несколько тысяч, сожмите журнал до минимума и одним шагом увеличьте до нужного размера командой ALTER DATABASE ... MODIFY FILE (... SIZE = 4096MB).
Автоматизация обслуживания и контроль места на диске
В редакциях Standard и Enterprise есть SQL Server Agent и планы обслуживания. В SSMS откройте Management → Maintenance Plans, создайте план через мастер и добавьте задачи Back Up Database (Full) и Back Up Database (Transaction Log) с разным расписанием. Туда же добавьте задачу очистки старых файлов копий, иначе место закончится уже на диске резервных копий.
В редакции Express агента нет. Копии запускают через Планировщик заданий Windows и утилиту sqlcmd. Пример bat-файла для копии журнала:
@echo off
set DT=%date:~6,4%%date:~3,2%%date:~0,2%_%time:~0,2%%time:~3,2%
set DT=%DT: =0%
sqlcmd -S .\SQLEXPRESS -E -Q "BACKUP LOG [buh_base] TO DISK = N'D:\Backup\buh_base_%DT%.trn'"
Разбор даты в bat зависит от региональных настроек Windows. Проверьте, какое имя файла получается на вашем сервере, прежде чем ставить задание в расписание. Учтите и ограничение Express: размер файла данных одной базы не больше 10 ГБ, журнал в этот лимит не входит.
Не включайте в планах обслуживания задачу Shrink Database и параметр AUTO_SHRINK. Регулярное сжатие бесполезно: журнал снова растёт, сервер тратит ресурсы на приращения, а сжатие файла данных фрагментирует индексы.
Для контроля места:
- 📊 раз в неделю смотрите
DBCC SQLPERF(LOGSPACE)или отчётDisk Usageв SSMS (правой кнопкой по базе,Reports → Standard Reports); - 🔔 настройте оповещение SQL Server Agent на ошибку 9002 — это ошибка переполнения журнала;
- 💾 держите журналы на отдельном томе, чтобы рост лога не останавливал систему и файлы данных.
Ошибка 9002 в 1С обычно видна пользователям как отказ при записи документа с текстом от СУБД: The transaction log for database 'buh_base' is full due to 'LOG_BACKUP'. В конце сообщения та же причина, что в log_reuse_wait_desc.
Если файл журнала не уменьшается
Чего делать нельзя: отключать базу (Detach), удалять LDF и подключать .mdf без журнала. Если база была закрыта некорректно, SQL Server не сможет восстановить согласованность без лога, и база перейдёт в состояние SUSPECT или RECOVERY_PENDING. Восстанавливать её придётся из копии.