Ситуация, когда в справочнике системы «1С:Предприятие 7.7» появляются две записи с абсолютно одинаковыми внутренними идентификаторами ID и кодами CODE, на первый взгляд кажется мистикой. Ведь платформа должна жестко контролировать уникальность ID при записи любого объекта. Однако в файловом варианте (DBF) такая проблема встречается, и она является следствием технических особенностей работы движка базы данных и сетевых протоколов Windows. В этой статье мы подробно разберем, почему это происходит и как корректно устранить дубли, не повредив структуру базы данных.
Для начала проанализируем ситуацию: формат DBF сам по себе не содержит встроенных механизмов контроля уникальности полей (как, например, первичные ключи в SQL). Вся логика контроля уникальности в «семерке» лежит на плечах программного движка 1С и индексных файлов .cdx. Рассмотрим основные сценарии, которые приводят к «раздвоению» записи:
ID.Enter данные записываются в новую позицию, фактически дублируя запись..cdx поврежден или не успел обновиться из-за кратковременного разрыва связи, проверка на уникальность ID выдает ложноотрицательный результат. Система «не видит» существующий ID в индексе и разрешает запись физического дубля в .dbf.Просто пометить объект на удаление и запустить «Удаление помеченных объектов» в 1С в данном случае часто невозможно или неэффективно, так как система может выдавать ошибки при попытке обращения к дубликату. Посмотрим на алгоритм правильного лечения базы:
Шаг 1: Подготовка и поиск нужного файла.
Прежде всего, нам нужно определить, в какой таблице находится проблема. Справочники хранятся в файлах вида SC*.dbf (например, SC123.dbf). Найти соответствие имени файла конкретному справочнику можно в файле 1CV7.DD (или .DDS для SQL-версии), открыв его любым текстовым редактором.
Шаг 2: Использование стороннего редактора.
Для удаления дубля нам потребуется утилита для работы с DBF-файлами (например, DBFViewer или CDBF). Важно: все действия выполняются только после создания резервной копии базы и в монопольном режиме (все пользователи должны выйти из 1С).
Шаг 3: Физическое удаление.
В редакторе DBF найдите проблемные записи по значению ID. Вы увидите две строки с одинаковым содержимым. Рассмотрим подробнее процедуру удаления:
Pack физически пересобирает файл, полностью удаляя строки, помеченные «звездочкой», и сдвигая остальные записи. Без упаковки запись останется в файле, и 1С продолжит её видеть.После того как мы вмешались в структуру .dbf извне, индексные файлы .cdx стали невалидными. Проанализируем ситуацию: индексы все еще хранят ссылки на позиции в файле, которые изменились после упаковки. Если запустить систему сейчас, вы получите критическую ошибку или еще большее повреждение данных.
Выполните следующие действия:
.cdx.Чтобы подобные «чудеса» не повторялись, проанализируем настройки вашего сервера и конфигурации. Мы рекомендуем предпринять следующие шаги:
Настройка сетевого протокола:
Если база лежит на Windows-сервере, необходимо настроить параметры реестра для управления кэшированием. Посмотрите на параметры DirectoryCacheLifetime, FileNotFoundCacheLifetime и FileInfoCacheLifetime. Установка их в значение 0 часто решает проблемы с «призраками» записей в 1С 7.7. Также рассмотрите возможность отключения SMB v2/v3 в пользу SMB v1, хотя это и снижает безопасность сети.
Изменение логики работы в конфигурации:
Если дубли возникают часто в конкретном справочнике, проанализируйте настройки его формы списка. Хорошей практикой считается отключение возможности «Редактировать в списке» для справочников с большим количеством полей или сложными отборами. Безопаснее редактировать элементы только в форме диалога.
Пример кода для программной проверки:
Если вы подозреваете наличие дублей, можно написать простую обработку для их поиска. Проанализируем пример кода, который обходит справочник и ищет совпадения ID (хотя штатно ID получить через ТекущийЭлемент() сложно, можно проверять уникальность сочетания кода и наименования):
Спр = СоздатьОбъект("Справочник.Номенклатура");
ТЗ = СоздатьОбъект("ТаблицаЗначений");
ТЗ.НоваяКолонка("Код");
ТЗ.НоваяКолонка("Элемент");
Спр.ВыбратьЭлементы();
Пока Спр.ПолучитьЭлемент() = 1 Цикл
ТЗ.НоваяСтрока();
ТЗ.Код = Спр.Код;
ТЗ.Элемент = Спр.ТекущийЭлемент();
КонецЦикла;
ТЗ.Группировать("Код", "Элемент"); // Если есть полные дубли, этот метод может вести себя непредсказуемо
// Лучше выгрузить в ТЗ и программно сравнить количество строк до и после свертки
В завершение отметим, что наиболее радикальным и надежным способом избавления от проблем DBF является перевод базы данных на SQL-версию 1С:Предприятия 7.7. В SQL-варианте контроль уникальности ID обеспечивается на уровне СУБД, что полностью исключает появление физических дублей.