Как исправить ошибку «Имеются записи с одинаковыми измерениями» при обновлении конфигурации?

Программист 1С v8.3 (Обычные формы) Сфера услуг, туризм и социальный сектор
← На главную

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

Разберем детально механизм возникновения этой проблемы, выясним, почему записи возвращаются обратно в регистр сведений, и рассмотрим проверенные способы успешного обновления конфигурации.

Почему возникает ошибка реструктуризации

Механизм обновления платформы 1С устроен так, что при изменении состава или типов измерений регистра сведений в СУБД формируется новая таблица. В нее переносятся данные из старой таблицы, после чего накладывается уникальный индекс по комбинации измерений. Ошибка возникает в следующих случаях:

  1. Удаление измерения. Если разработчик в новой редакции удалил одно из измерений, записи, которые ранее отличались только этим значением, становятся абсолютными дублями.
  2. Усечение длины строки. При сокращении длины строкового измерения строки, совпадающие по начальным символам, после усечения образуют одинаковые ключи.
  3. Сужение составного типа. Если измерение имело составной тип и один из типов был исключен, все ссылки исключенного типа при переносе превращаются в пустые значения, что также приводит к неуникальности строк.

Почему регистр заполняется повторно после очистки

Проанализируем фрагмент кода, который часто размещают в общих модулях конфигураций для сохранения состояния пользовательского интерфейса:


Процедура СохрЗнач(Форма, Реквизит, Значение, Вариант = "") Экспорт

	#Если ТолстыйКлиентОбычноеПриложение ИЛИ ТолстыйКлиентУправляемоеПриложение Тогда
	СохранитьЗначение(Питание_НаСервере.ПолучитьИдентификаторФормы(Форма)+"_"+Реквизит, Значение);
	#Иначе
	
	Идентификатор = Питание_НаСервере.ПолучитьИдентификаторФормы(Форма)+"_"+Реквизит;
	Пользователь = ПараметрыСеанса.ТекущийПользователь;
	
	НаборЗаписей = РегистрыСведений.Питание_ХранилищеНастроек.СоздатьНаборЗаписей();
	НаборЗаписей.Отбор.Идентификатор.Установить(Идентификатор);
	НаборЗаписей.Отбор.Пользователь.Установить(Пользователь);
	НаборЗаписей.Отбор.Вариант.Установить(Вариант);

	НоваяЗапись = НаборЗаписей.Добавить();
	НоваяЗапись.Идентификатор	= Идентификатор;
	НоваяЗапись.Пользователь	= Пользователь;
	НоваяЗапись.Вариант			= Вариант;
	НоваяЗапись.Значение		= Новый ХранилищеЗначения(Значение);
	НаборЗаписей.Записать();
	
	#КонецЕсли

КонецПроцедуры

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

Способ 1. Аварийное завершение сеанса после очистки

Рассмотрим самый быстрый способ предотвратить срабатывание обработчиков закрытия форм:

  1. Открываем информационную базу в режиме «1С:Предприятие» и программно очищаем проблемный регистр через внешнюю обработку пустым набором записей.
  2. Не закрываем окно программы крестиком или через главное меню базы.
  3. Запускаем «Диспетчер задач» операционной системы и принудительно снимаем процесс 1cv8.exe (либо выполняем команду taskkill /f /im 1cv8.exe).
  4. Открываем конфигуратор и запускаем реструктуризацию и обновление базы данных (клавиша F7). Так как код закрытия форм не сработал, регистр останется абсолютно пустым, и дубли не появятся.

Способ 2. Поиск конфликтующих строк запросом

Если в регистре содержатся важные пользовательские настройки, которые нежелательно полностью удалять, локализуем конфликтные данные. Напишем запрос к регистру по тем измерениям, которые останутся в целевой конфигурации после обновления:


ВЫБРАТЬ
    Идентификатор,
    Пользователь,
    КОЛИЧЕСТВО(*) КАК КоличествоДублей
ИЗ
    РегистрСведений.Питание_ХранилищеНастроек
СГРУППИРОВАТЬ ПО
    Идентификатор,
    Пользователь
ИМЕЮЩИЕ
    КОЛИЧЕСТВО(*) > 1

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

Способ 3. Очистка таблицы на уровне СУБД

В клиент-серверном варианте работы информационной базы можно полностью исключить влияние клиентских сеансов и фоновых заданий:

  1. Устанавливаем в консоли администрирования кластера серверов 1С блокировку начала сеансов и регламентных заданий.
  2. С помощью функции ПолучитьСтруктуруХраненияБазыДанных() определяем имя физической таблицы СУБД, соответствующей регистру.
  3. Останавливаем службу сервера 1С или завершаем все соединения к базе.
  4. В среде управления СУБД (например, SQL Server Management Studio) выполняем команду TRUNCATE TABLE для найденной таблицы.
  5. Запускаем сервер 1С, открываем конфигуратор с ключом разрешения /UC и завершаем реструктуризацию.

Способ 4. Временная корректировка кода сохранения

Если конфигурация уже находится на поддержке с возможностью редактирования, можно временно отключить процедуру сохранения настроек:

  1. Заходим в процедуру СохрЗнач общего модуля и комментируем вызов НаборЗаписей.Записать().
  2. Применяем изменения (F7).
  3. Запускаем сеанс «1С:Предприятия», штатно очищаем регистр сведений и выходим — обработчик закрытия больше ничего не запишет в базу.
  4. Выполняем основное обновление на новый релиз конфигурации.
← На главную