Почему пропадают записи в регистре сведений при программном добавлении и как это исправить?

Программист 1С v8.3 (Управляемые формы) IT и автоматизация бизнеса
← На главную

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

Разберем механизм транзакций и неявных откатов

Первое, на что нам следует обратить внимание — это контекст выполнения кода. В 1С запись в регистр часто происходит в рамках транзакции более крупного объекта, например, документа. Рассмотрим ситуацию: в процедуре ОбработкаПроведения документа создается запись в регистре. Если после выполнения строки кода с методом Записать() для регистра в коде документа возникнет ошибка или будет установлено значение Отказ = Истина, вся транзакция будет откачена.

Проанализируем, почему Журнал регистрации может вводить в заблуждение. Платформа фиксирует событие «Изменение данных» в момент обращения к таблице. В некоторых версиях платформы или при определенных настройках ЖР событие записи набора может попасть в лог до того, как транзакция в основной СУБД (SQL) будет окончательно зафиксирована (Commit). Если происходит откат (Rollback), изменения в таблицах базы данных исчезают, а запись в текстовом или SQLite-файле журнала регистрации остается. Таким образом, мы видим «призрак» записи.

Проанализируем работу с объектом НаборЗаписей

Одной из наиболее частых причин отсутствия данных является некорректное использование объекта РегистрСведенийНаборЗаписей. Выясним, как параметр Замещать влияет на конечный результат. Посмотрим на типовой пример кода:


НаборЗаписей = РегистрыСведений.ИсторияСтатусов.СоздатьНаборЗаписей();
НаборЗаписей.Отбор.Объект.Установить(СсылкаНаОбъект);
// Если мы просто вызовем Записать() без добавления строк...
НаборЗаписей.Записать(Истина); 

В данном примере, если в наборе нет ни одной строки, метод Записать(Истина) просто очистит все записи в регистре по указанному отбору. В Журнале регистрации это событие будет выглядеть как «Изменение», но фактически вы удалили данные. Чтобы избежать этого, всегда проверяйте количество строк в наборе или используйте параметр Ложь, если ваша задача — только добавление записей без очистки старых по фильтру.

Рассмотрим проблему уникальности ключа записи

Если регистр сведений является непериодическим, то совокупность его измерений образует уникальный ключ. Если мы в цикле или в разных сеансах записываем данные с одинаковыми измерениями, каждая последующая запись будет просто перезаписывать предыдущую. Проанализируем ситуацию: код отработал 1000 раз, в Журнале регистрации мы видим 1000 событий, а в регистре — всего 1 запись. Это не пропажа данных, а логика работы платформы 1С по обеспечению уникальности ключа.

Для решения этой проблемы проверим, все ли измерения заполнены корректно. Если хотя бы одно измерение, которое должно делать запись уникальной (например, Дата в периодическом регистре или Идентификатор в обычном), заполнено значением по умолчанию (пустая ссылка или дата 01.01.0001), то новые записи будут «схлопываться».

Выясним роль RLS и прав доступа

Иногда запись физически существует в базе данных, но пользователь (и даже разработчик) ее не видит. Проанализируем влияние механизма RLS (Record Level Security). Если для регистра настроены ограничения на уровне записей, то запрос в консоли, запущенный под пользователем с ограниченными правами, вернет пустой результат.

Рекомендуем всегда проверять наличие «пропавших» записей под пользователем с полными правами и отключенными ограничениями. Также стоит использовать Консоль запросов с флагом «Выполнять без учета RLS», чтобы убедиться, что данные действительно отсутствуют в СУБД.

Разберем шаги по диагностике и правильному логированию

Чтобы больше не «гадать на кофейной гуще», внедрим расширенное логирование. Предварительный анализ конфигурации на наличие ошибок поможет выявить логические просчеты. Вместо того чтобы полагаться на системные сообщения ЖР, создадим свою запись, которая даст нам полную картину в момент совершения транзакции.

  1. Добавим проверку количества записей: перед вызовом метода Записать() проверим, не пуст ли набор.
  2. Используем блок Попытка-Исключение: это позволит перехватить системные ошибки СУБД (например, блокировки или нарушение целостности).
  3. Записываем подробности в ЖР: фиксируем значения ключевых измерений.

Посмотрим на пример надежного кода записи:


НаборЗаписей = РегистрыСведений.МойРегистр.СоздатьНаборЗаписей();
НаборЗаписей.Отбор.КлючОбъекта.Установить(ПараметрОбъект);

НоваяЗапись = НаборЗаписей.Добавить();
НоваяЗапись.КлючОбъекта = ПараметрОбъект;
НоваяЗапись.Значение = ПараметрЗначение;

Попытка
    // Параметр Ложь гарантирует, что мы не затрем существующие данные по другим отборам
    НаборЗаписей.Записать(Ложь);
    
    // Дополнительное подтверждение в журнал для отладки
    ТекстСообщения = СтрШаблон("Запись успешно создана. Объект: %1, Значение: %2", ПараметрОбъект, ПараметрЗначение);
    ЗаписьЖурналаРегистрации("ПрограммноеДобавлениеЗаписи", УровеньЖурналаРегистрации.Информация, , , ТекстСообщения);
Исключение
    ТекстОшибки = СтрШаблон("Ошибка при записи в регистр: %1", ОписаниеОшибки());
    ЗаписьЖурналаРегистрации("ПрограммноеДобавлениеЗаписи", УровеньЖурналаРегистрации.Ошибка, , , ТекстОшибки);
    ВызватьИсключение; // Пробрасываем ошибку дальше, чтобы транзакция документа тоже откатилась
КонецПопытки;

Подведем итоги и сформируем рекомендации

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

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

← На главную