Почему удаленная табличная часть остается в базе SQL и как избежать ошибки SDBL?

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

В процессе активной разработки в среде 1С:Предприятие программисты регулярно сталкиваются с необходимостью изменения структуры метаданных: удалением реквизитов, справочников, документов или их табличных частей. Обычно эти действия проходят бесшовно, однако бывают ситуации, когда после удаления табличной части в Конфигураторе и успешного обновления конфигурации базы данных, физическая таблица в СУБД MS SQL Server со всеми записями остается нетронутой. При этом программный метод ПолучитьСтруктуруХраненияБазыДанных() её больше не видит.

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

Выясняем причину: почему таблица зависает в SQL?

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

  1. Сбой транзакции при реструктуризации базы данных. Процесс обновления конфигурации БД в 1С устроен как сложная многоступенчатая транзакция. Платформа создает новые временные таблицы, переносит туда актуальные данные, перестраивает индексы и только в самом конце удаляет ставшие ненужными таблицы. Если на финальном этапе СУБД зафиксировала некритичную ошибку (например, таймаут блокировки из-за фонового задания, нехватку места в файле лога транзакций ldf или кратковременный сетевой сбой), транзакция удаления старой таблицы могла откатиться на уровне SQL Server. Однако на уровне метаданных 1С (в системных таблицах DBSchema и Params) изменения уже зафиксировались. Как результат — 1С «забывает» о существовании таблицы, а SQL продолжает её хранить.
  2. Особенности «Новой реструктуризации» платформы. Начиная с версии 8.3.11, в платформе доступен оптимизированный механизм реструктуризации. На практике в версиях 8.3.15–8.3.17 данный алгоритм нередко давал сбои, оставляя в базе данных «мусорные» таблицы старой структуры или временные объекты реструктуризации с суффиксами _NG и _NGS.
  3. Активные сеансы и блокировки кэша. Если процесс обновления запускался без монопольного режима (или при наличии «зависших» фонового сеанса или спящего подключения), СУБД могла заблокировать команду DROP TABLE, отложив или полностью проигнорировав физическое удаление объекта.

Чем опасны "осиротевшие" таблицы: лавина ошибок SDBL

Многие разработчики считают, что лишняя таблица в SQL — это лишь небольшая потеря дискового пространства. Однако это заблуждение. Самая большая опасность кроется в возникновении критической ошибки:

Ошибка SDBL: Ошибка обновления конфигурации базы данных. Для одного ссылочного кода существует более одной таблицы в базе данных.

Давайте проанализируем механизм генерации имен в 1С. Платформа выделяет внутренние целочисленные идентификаторы (ссылочные коды) для создаваемых объектов СУБД. Например, для документа выделяется код 40, а для его табличной части — код 41. Если вы восстанавливаете базу данных из резервной копии SQL без перезапуска службы сервера 1С, менеджер кластера (процесс rmngr.exe) продолжает хранить старый кэш распределения этих кодов.

При создании нового объекта метаданных платформа может выдать ему тот же свободный, по её мнению, числовой код. В процессе обновления конфигурации 1С пытается создать в SQL-базе таблицу с этим кодом, обращается к СУБД и обнаруживает, что физическая таблица с таким именем (оставшаяся от удаленного ранее объекта) уже существует и содержит данные. Происходит жесткий конфликт SDBL, блокирующий любые дальнейшие обновления конфигурации.

Как решить проблему: пошаговые сценарии

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

Способ 1. Ручное удаление таблицы средствами SQL Server (DROP TABLE)

Поскольку платформа 1С через функцию ПолучитьСтруктуруХраненияБазыДанных() данную таблицу больше не идентифицирует, для системы эта таблица является абсолютным мусором. Её можно безопасно удалить вручную.

Важно: Перед выполнением любых прямых запросов к СУБД обязательно сделайте резервную копию базы данных средствами SQL Server!

Разберем по шагам процесс удаления таблицы через MS SQL Server Management Studio (SSMS):

  1. Откройте SSMS и подключитесь к вашему серверу баз данных под учетной записью администратора (например, sa).
  2. Найдите нужную базу данных и откройте окно создания нового запроса (кнопка New Query).
  3. Для безопасности сначала проверим наличие таблицы и количество записей в ней, чтобы случайно не удалить нужные данные:

SELECT COUNT(*) FROM dbo._Document40_VT41;

  1. Убедившись, что это именно та удаленная табличная часть, выполните команду удаления объекта:

IF OBJECT_ID('dbo._Document40_VT41', 'U') IS NOT NULL
    DROP TABLE dbo._Document40_VT41;

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

Способ 2. Выгрузка и загрузка через файл данных (.dt)

Это самый надежный, штатный и безопасный способ избавления от любого физического мусора в СУБД, рекомендуемый самой фирмой 1С.

Проанализируем этот процесс:

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

Способ 3. Сброс кэша сервера 1С и профилактика конфликтов

Если вы часто проводите манипуляции с восстановлением баз из SQL-бэкапов (особенно в тестовых контурах разработки), возьмите за железное правило:

После восстановления базы данных средствами СУБД всегда перезапускайте службу сервера 1С:Предприятия!

Если нет возможности перезапустить всю службу целиком (например, на рабочем сервере запущено множество других баз), выполните перезапуск процесса rmngr.exe или удалите базу из списка консоли администрирования 1С и добавьте её заново. Это принудительно очистит внутренний кэш менеджера кластера и предотвратит наложение новых транзакций на старые физические таблицы СУБД.

Что делать, если ошибка SDBL "Для одного ссылочного кода..." уже возникла?

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

  1. Откройте Конфигуратор и найдите объект метаданных, на котором происходит сбой (или любой другой крупный объект, если точное имя проблемной таблицы не очевидно).
  2. Добавьте к этому объекту новый временный реквизит с простым типом данных (например, ВременныйРеквизит с типом Булево).
  3. Запустите обновление конфигурации базы данных (клавиша F7). Данное действие заставит платформу принудительно запустить полную реструктуризацию этого объекта, в ходе которой она перезапишет схему метаданных в СУБД и корректно перераспределит внутренние идентификаторы.
  4. После успешного обновления удалите созданный временный реквизит и повторно обновите базу данных.

Использование этого несложного приема позволяет быстро вернуть базу данных в рабочее состояние без ручной корректировки системных таблиц СУБД.

← На главную