При активном использовании обмена данными между конфигурациями 1С (например, между 1С:Зарплата и управление персоналом и 1С:Бухгалтерия предприятия 3.0) пользователи часто сталкиваются с проблемой накопления огромного количества предупреждений. Одной из самых ресурсоемких категорий являются предупреждения «Непринятые по дате запрета». Когда счетчик таких записей переваливает за несколько сотен тысяч или миллионов, стандартная форма «Предупреждения при синхронизации данных» перестает открываться, вызывая полное зависание сеанса. Рассмотрим, как решить эту проблему на уровне разработчика, используя прямой доступ к данным регистров.
Проанализируем ситуацию: почему стандартный интерфейс не справляется? Дело в том, что при открытии вкладки с предупреждениями система пытается не просто вывести список ссылок, а динамически вычислить количество записей, проанализировать их тип и подготовить данные для отображения. Если в базе скопились миллионы записей, механизм БСП (Библиотеки стандартных подсистем) начинает считывать тяжелые бинарные данные из хранилищ значений, что приводит к перегрузке оперативной памяти и бесконечному ожиданию ответа от сервера СУБД.
Для решения задачи нам необходимо знать, где именно физически хранятся эти данные. Вопреки распространенному мнению, информация рассредоточена по нескольким местам:
ВерсииОбъектов — это основное хранилище. Когда объект (документ или справочник) приходит по обмену, но не может быть записан из-за установленной даты запрета загрузки, система сохраняет его «тело» (в формате XML) именно сюда.РезультатыОбменаДанными — здесь хранятся общие сведения о возникших проблемах (непроведенные документы, незаполненные реквизиты). Однако для «непринятых по дате запрета» этот регистр часто содержит лишь вторичную информацию.СостоянияОбъектовИнформационныхБаз — вспомогательный регистр, который может хранить кэшированные статусы объектов обмена.Основной объем данных, вызывающий «мертвое» зависание, находится в регистре ВерсииОбъектов. Каждая запись в этом регистре имеет поле ТипВерсии. Для интересующих нас предупреждений это поле принимает значение Непринятый по дате запрета объект существует в базе данных (соответствует значению перечисления ТипыВерсийОбъектов.НепринятыйПоДатеЗапрета).
Посмотрим на пример кода, который поможет нам определить количество таких записей, не открывая форму:
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| КОЛИЧЕСТВО(*) КАК КолВо
|ИЗ
| РегистрСведений.ВерсииОбъектов КАК ВерсииОбъектов
|ГДЕ
| ВерсииОбъектов.ТипВерсии = ЗНАЧЕНИЕ(Перечисление.ТипыВерсийОбъектов.НепринятыйПоДатеЗапрета)";
РезультатЗапроса = Запрос.Выполнить();
Выборка = РезультатЗапроса.Выбрать();
Если Выборка.Следующий() Тогда
Сообщить("Количество проблемных записей: " + Выборка.КолВо);
КонецЕсли;
Если число в сообщении превышает 100 000, удаление через стандартную консоль запросов или обработку «Групповое изменение реквизитов» может затянуться на часы или также привести к зависанию из-за длительных транзакций.
Наиболее безопасным и быстрым способом очистки является программное удаление с использованием набора записей с установленным фильтром. Проанализируем ситуацию: удаление через Объект.Удалить() для каждой записи создает отдельную транзакцию и обновляет индексы, что крайне медленно. Использование НаборЗаписей позволяет очистить данные эффективнее.
Рассмотрим по шагам алгоритм удаления данных из РегистрСведений.ВерсииОбъектов:
Набор = РегистрыСведений.ВерсииОбъектов.СоздатьНаборЗаписей();
// Устанавливаем фильтр по типу версии
Набор.Отбор.ТипВерсии.Установить(Перечисления.ТипыВерсийОбъектов.НепринятыйПоДатеЗапрета);
// Если мы хотим очистить ВООБЩЕ ВСЕ предупреждения этого типа:
Набор.Записать();
// Пустой набор, записанный с фильтром, удаляет все записи, подпадающие под этот фильтр.
Важный момент: Если записей миллионы, даже такая операция может «подвесить» таблицу на уровне СУБД. В таких случаях рекомендуется выполнять удаление порциями (например, по 5-10 тысяч записей) в цикле, фиксируя транзакции. Однако, поскольку в ВерсииОбъектов составной ключ, фильтрация для порционного удаления может быть затруднена. В большинстве случаев запись пустого набора с фильтром по ТипВерсии отрабатывает корректно.
После того как мы удалили тяжелые данные из версий объектов, необходимо почистить «шапки» предупреждений в регистре РезультатыОбменаДанными. Это позволит интерфейсу 1С окончательно понять, что предупреждений больше нет.
Проанализируем пример кода для очистки этого регистра:
НаборРезультатов = РегистрыСведений.РезультатыОбменаДанными.СоздатьНаборЗаписей();
// Здесь фильтрация может быть сложнее, так как тип проблемы не всегда явно указан в измерениях.
// Обычно очищают записи, где ТипПроблемы соответствует НепринятымПоДатеЗапрета.
НаборРезультатов.Отбор.ТипПроблемы.Установить(Перечисления.ТипыПроблемОбменаДанными.НепринятыйПоДатеЗапрета);
НаборРезультатов.Записать();
В современных версиях 1С:Бухгалтерия 3.0 предусмотрены регламентные задания по очистке версий. Посмотрим, как ими воспользоваться:
Однако помните, что стандартная очистка часто игнорирует «Непринятые» объекты, считая их важными для пользователя. Поэтому ручная очистка через программный код, описанная выше, остается самым надежным методом при критических объемах данных.
Чтобы база снова не зависла через месяц, рекомендуем выполнить следующие действия:
ВерсииОбъектов с типом НепринятыйПоДатеЗапрета.Таким образом, мы проанализировали механизм хранения предупреждений синхронизации, выявили «виновника» зависаний в лице регистра Версии объектов и научились эффективно очищать его программными средствами. Это позволяет восстановить работоспособность интерфейса синхронизации без необходимости переустановки обмена или обращения к средствам SQL.