Почему пропадают данные из 1С без следов в журнале регистрации?

Системный администратор 1С v8.3 (Обычные формы) 1С:Управление торговлей Управленческий учет Торговля и дистрибуция
← На главную

Ситуация, когда объект (документ или элемент справочника) был создан, распечатан и в Журнале Регистрации (ЖР) зафиксирована запись о его добавлении, но спустя время объект бесследно исчезает из базы, является одной из самых сложных в диагностике. Особенно критично это выглядит, когда в ЖР отсутствуют записи об удалении. Разберем детально причины этого явления и методы расследования подобных инцидентов.

Анализ механизма транзакций 1С и SQL

Первое, что необходимо понять: запись в Журнале Регистрации со статусом «Транзакция завершена: Зафиксирована» не всегда означает физическое наличие данных в таблицах MSSQL в долгосрочной перспективе. Проанализируем, как это происходит. Механизм 1С:Предприятие работает с транзакциями многослойно. Существует транзакция на уровне платформы 1С и транзакция на уровне СУБД.

Одной из наиболее вероятных причин является так называемая «забытая транзакция». Рассмотрим ситуацию: где-то в программном коде (в общем модуле или в подписке на событие) вызывается метод НачатьТранзакцию(), но при определенных условиях не вызывается ЗафиксироватьТранзакцию(). Если пользователь в рамках этой незакрытой транзакции создает документ и нажимает кнопку «Записать», платформа 1С воспринимает это как вложенную транзакцию. В Журнале Регистрации появляется запись «Добавление», так как вложенный этап прошел успешно.

Однако, если через некоторое время основная (верхнеуровневая) транзакция откатывается (например, по таймауту или из-за ошибки в коде), SQL-сервер выполняет ROLLBACK для всех данных, измененных с момента вызова первого НачатьТранзакцию(). При этом Журнал Регистрации 1С, особенно в текстовом формате .lgf, может сохранить запись о фиксации вложенной части, так как запись в лог и фиксация в БД — это не атомарная операция.

Пример проблемного кода, который может привести к подобному:


НачатьТранзакцию();
// ... какой-то сложный код обработки данных
Попытка
    // Создание документа пользователем в интерактивном режиме
    ДокументОбъект.Записать(РежимЗаписиДокумента.Запись);
    // В ЖР попадет запись "Зафиксирована", так как этот блок выполнен
Исключение
    // Если здесь нет ВызватьИсключение или ОтменитьТранзакцию, 
    // транзакция может "повиснуть"
КонецПопытки;
// Если до ЗафиксироватьТранзакцию() выполнение не дошло из-за ошибки выше,
// произойдет неявный откат всего пакета данных.

Влияние рестарта службы сервера 1С

Проанализируем ситуацию, связанную с перезапуском службы rphost или всего сервера 1С. В платформе 1С:Предприятие 8.3 запись журнала регистрации может буферизироваться. Если объект был записан, и запись о транзакции попала в буфер ЖР, но физическая запись в базу данных MSSQL еще не была окончательно подтверждена (например, из-за задержек дисковой подсистемы или особенностей работы кэша записи), внезапный рестарт службы может привести к потере данных в БД, при этом файл ЖР может успеть сохраниться на диске.

Также стоит учитывать вероятность «грязного чтения» из кэша. Если объект был создан в рамках транзакции, он может быть доступен для печати или просмотра другим сессиям (в зависимости от уровней изоляции), но после отката основной транзакции он исчезнет из таблиц _Document или _Reference.

Человеческий фактор и манипуляции с бэкапами

Рассмотрим гипотезу восстановления базы из резервной копии. Это единственный штатный сценарий, при котором в Журнале Регистрации запись о создании объекта есть, а самого объекта нет (и записи об удалении тоже нет). Если системный администратор развернул бэкап поверх рабочей базы, сделанный до момента создания злополучных документов, то состояние таблиц SQL откатится назад. При этом, если Журнал Регистрации хранится в виде файлов в каталоге сервера 1С (а не внутри БД), он останется «актуальным» и будет содержать записи о документах, которых в восстановленной базе уже нет.

Посмотрим, как проверить эту версию:

  1. Проверить системный лог SQL-сервера на предмет выполнения команд RESTORE DATABASE.
  2. Сравнить время изменения файлов базы данных .mdf и .ldf со временем возникновения инцидента.
  3. Изучить журналы планировщика задач на сервере (не запускались ли скрипты автоматического восстановления для тестов).

Особенности модели восстановления SIMPLE в MSSQL

Выясним причину, почему модель восстановления SIMPLE затрудняет расследование и может способствовать потере данных. В режиме SIMPLE SQL-сервер автоматически очищает журнал транзакций после прохождения контрольной точки (checkpoint). Если произошел сбой в момент фиксации данных, и система ушла в цикл восстановления (Recovery), шансы на откат незафиксированных данных возрастают, а возможности восстановить их из лога транзакций (Transaction Log) практически отсутствуют.

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

  1. Перевести базу данных в режим восстановления FULL. Это позволит использовать лог транзакций для детального анализа операций вплоть до конкретной секунды.
  2. Настроить регулярный бэкап журнала транзакций (например, каждые 15-30 минут).
  3. Включить Технологический Журнал (ТЖ) 1С с отслеживанием событий DBMSSQL и TLOCK. Это поможет увидеть реальные SQL-запросы, которые отправляет сервер приложений, и понять, был ли фактический COMMIT на уровне СУБД.

Прямое удаление через SQL

Нельзя исключать и прямой доступ к базе данных на уровне СУБД. Любое удаление данных через 1С (даже программное через Объект.Удалить()) всегда оставляет след в Журнале Регистрации. Однако выполнение скрипта DELETE FROM ... напрямую в SQL Management Studio проходит мимо механизмов логирования 1С. В этом случае в ЖР будет только запись о создании, а объект в базе исчезнет.

Чтобы исключить этот вариант, проанализируем план безопасности:

Итоговый алгоритм действий при пропаже данных

Если вы столкнулись с подобным случаем, выполните последовательно следующие действия:

  1. Проверьте нумерацию: если в нумерации документов образовалась «дыра» (пропуск номера), значит объект точно существовал и транзакция по присвоению номера прошла успешно.
  2. Анализ связанных таблиц: проверьте таблицы движений (регистры накопления, бухгалтерии). Иногда объект удаляется, а записи в регистрах остаются (если удаление было некорректным на уровне SQL).
  3. Проверьте версию платформы: в старых релизах 8.3.16 были специфические ошибки взаимодействия с MSSQL при разрыве соединений. Рассмотрите возможность обновления на стабильную ветку (например, 8.3.22 и выше).
  4. Журнал регистрации: проверьте, не было ли в этот период записей о «разделении файлов журнала» или ошибок записи в ЖР. В текстовом формате .lgf возможна порча индекса журнала.

Важный момент: если вы используете формат журнала .lgf, рассмотрите переход на новый формат .lgp (на базе SQLite). Он более устойчив к сбоям сервера и обеспечивает транзакционную целостность самих записей журнала, что минимизирует риск появления «ложных» записей о фиксации транзакций.

← На главную