gifts2017

Как я восстанавливал разрушенную базу. АКТ 2

Опубликовал Михаил Беляев (METAL) в раздел Администрирование - Тестирование и исправление

Приёмы, которые помогут тебе устранить рассинхронизацию данных и метаданнах (на уровне SQL)

ДИСКЛЕЙМЕР

Автор не несет никакой ответственности, кроме как за достоверность предоставленной информации.
Всю нижеследующую информацию воспринимать и использовать на свой страх и риск. 

ПРЕДЫСТОРИЯ ЗДЕСЬ

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

Но и работать с базой было нельзя. Открытие формы констант, определенных документов, попытка обновить конфигурацию ИБ и другие обычные действия - давали исключения уровня СУБД с добровольно-принудительным предложением завершить работу :) Читайте ниже о том, как я победил каждое из них.

Примеры ошибок и приёмы лечения

Проблема №1. Нехватка поля (реквизита объекта либо константы)

Симптомы: 

При попытке открыть форму объекта/констант/etc видим

Ошибка СУБД:
Microsoft OLE DB Provider for SQL Server: Invalid column name '_Fld123'

Диагноз:

Очевидно, что в схеме базы (в "метаданных") поле есть. А в реальной таблице - нет.
То есть в новом релизе было добавлено поле, но так как не было реструктуризации - его нет в реальных таблицах.

Что делать:

Как ни странно, добавить недостающее поле :) Для этого нам нужно знать, в какую таблицу и какого типа.

В расследовании поможет профайлер (MS SQL Profiler).

Запускаем трассировку, воспроизводим ошибку, делаем поиск по имени поля, в идеале попадаем в запрос вида как на картинке.

Имя таблицы - в первой строке запроса, тип поля - параметр справа от самого поля.

Нехватка поля, 1

 

В итоге у нас есть: куда и что добавить, и какого типа.

Добавим же это поле в SQL-студии, для этого нам поможет оператор ALTER TABLE ... ADD 

После добавления поля в таблицу - во всех строках в этом поле будет значение NULL, что не годится, так как как правило вызывает ошибки преобразования типов (например в поле должно быть Булево, и есть строки кода

Если ЭтоДобавленноеПоле Тогда

или

РеквизитТипаБулево=ЭтоДобавленноеПоле

)

поэтому заполним сразу неким значением по-умолчанию

Я обычно заполнял единичкой (для ссылок, чисел и булево) либо пустой строкой '' для типа ntext

Пример скрипта

-- добавление в таблицу новой колонки
ALTER TABLE ИмяТаблицы ADD ИмяПоля ТипПоля NULL;
-- заполнение дефолтным значением
UPDATE ИмяТаблицы
SET ИмяПоля=ДефолтноеЗначение 

Добавление недостающих колонок

При выполнении обращайте внимание на контекст выполнения, то есть в какой базе будет выполнен запрос. Для уверенности можно использовать явное указание через USE

USE target_base
GO

Выделяем нужный фрагмент, выполняем выделенный фрагмент текста запроса нажатием на Execute

Если всё ок - внизу отображается количество обработанных строк (цифры будут меняться в зависимости от реального количества строк в обрабатываемых таблицах)

Если всё сделали правильно - ошибка исчезнет.

Проблема №2. Наоборот, лишнее поле

Симптомы: 

При попытке записать объект видим

Ошибка СУБД:
Microsoft OLE DB Provider for SQL Server: Cannot insert the value NULL into column '_Fld123'table 'SufferedBase.dbo._Document234'column does not allow nullsINSERT fails.

Напрямую не мешает, но косвенно жить не даёт :)

Дело в том, что многие поля на уровне SQL имеют ограничение NOT NULL. То есть NULL туда записать нельзя. И при записи 1С явно передаёт в SQL через INSERT какие поля и какими значениями заполнить.

И если в SQL есть поле, про которое 1С не знает - значит неявно получится попытка записать в это поле NULL. И будет следующая ошибка 

Ошибка вставки НУЛЛ

Диагноз:

В новом релизе поле было удалено. В схеме базы (в "метаданных") поля уже нет. А в реальной таблице - осталось.

Что делать:

Решением будет удалить это поле из таблицы SQL.

С помощью конструкции 

ALTER TABLE ИмяТаблицы DROP COLUMN ИмяПоля;

Ниже весь процесс (в красной рамке лишние поля, их нет в схеме базы, что видно в запущенной в 1С:Предприятии обработке, которая показывает структуру базы данных. Таких существует много, пользоваться можете любой, моя опубликована здесь )

Лишние реквизиты - как лечить


Проблема №3. Количество полей в реальной таблице SQL отличается от количества полей в метаданных

Симптомы: 

При попытке записать объект с заполненной табличной частью

Ошибка СУБД:
Microsoft OLE DB Provider for SQL Server: Column name or number of supplied values does not match table definition.

Диагноз:

Как и в прошлом случае, в схеме базы (в "метаданных") поля нет, в реальной таблице - осталось.
Разница с прошлой проблемой: расхождение в полях произошло в табличной части, а не в шапке.

Что делать:

Как и в прошлом случае, решением будет удалить это поле из таблицы SQL.

Но на этот раз - расследовать немного сложнее, так как нам неизвестен ни один идентификатор - ни проблемной таблицы, ни поля. 

Как и раньше, ищем проблемный запрос профайлером. 

Разное количество полей в ТЧпосчитать реквизиты в запросе 

Самое интересное здесь - имя таблицы, куда идёт вставка. 

После чего обращаем пристальное внимание на поля этой таблицы, и сравниваем их с полями этой же таблицы, но той базы, которую использовали для лечения (живая база, откуда брали служебные таблицы Config и тд).

Для этого сравнения есть разные способы, самый эффективный на мой взгляд: получить скрипты создания этих таблиц (подробно способ описан в решении проблемы №4, ниже)

И сравнить их тексты, вот так:

Сравнение скриптов добавления таблиц для вычисления разницы между полями

Таким образом, видим в новой проблемной базе 2 лишних поля, удаляем их описанным ранее способом, и проблема решается. Если всё правильно расследовали и сделали, конечно :)

 

Вариация на тему

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

Проблема №4. Нехватка целиком какой-то таблицы

Симптомы: 

В разных транзакциях вот такое:

Ошибка СУБД:
Microsoft OLE DB Provider for SQL Server: Invalid object name ...

Диагноз:

В схеме базы (в "метаданных") таблица есть, а в базе - такая отсутствует.
В новом релизе таблицу добавили, но так как реструктуризации не было, в базе её нет.

Что делать:

Добавить.

Самое простое - добавить из живой базы

  1. Находим там эту таблицу
  2. Правый клик на ней
  3. Script Table As
  4. CREATE TO
  5. New Query...
  6. Меняем там имя целевой базы
  7. Выполняем

Нехватка таблицы

Радуемся, если проблема решались (опционально)
:)


Ещё кое-что

Был еще ряд проблем, которые не удалось классифицировать. Кратко о них:

  1. При реструктуризации исключение, жалоба на нехватку таблицы EDBT...
    Как выяснилось, так кодируется таблица внешнего источника данных
    После удаления этого внешнего источника данных из Конфигуратора - проблема решилась
  2. Словил ошибку 

    Either the parameter @objname is ambiguous or the claimed @objtype (COLUMN) is wrong

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

Если есть конфигурация поломанной базы (CF)...

, то можно восстановить методом проще. Раскрыть этот CF в пустую базу, и оттуда перетащить в битую базу таблицу Config

Вместо эпилога

Вопросы, конструктивную критику, пожелания, дополнения и предложения, как обычно в комментарии.
Если статья оказалась полезной/интересной - Вы знаете что делать :)

И еще.. Интересно ли кому-то легкий мануал по соответствию имён таблиц "SQL-1C" ?
Который позволит однозначно ответить на вопрос "А какой таблице 1С соответствует SQL-ная _SeqB567" и все аналогичные

См. также

Подписаться Добавить вознаграждение

Комментарии

1. Михаил Максимов (МихаилМ) 31.08.15 13:15
предлагаю автору перейти от эмпирического поиска ошибок к аналитическому.
разобраться , как 1с8 сопоставляет реквизиты и поля бд.

Для этого научиться парсить запись dbnames таблицы params , записи таблицы config.
по их данным строить сопоставления имен метаданных и имен таблиц и полей.
подсказка: 1с хранит описания метаданных в виде текста в кодировке utf8 (сжатого deflate)
tsql не умеет работать с utf . а xml умеет. н уи про BOM не забываем.


Светлый ум; ojiojiowka; +2 Ответить 2
2. Михаил Беляев (METAL) 31.08.15 13:48
(1) МихаилМ, учитывая Ваш совет - что конкретно можно было сделать лучше в рамках данной статьи?

А так, согласен, как ра3 собирался распарсить эти таблицы, посмотреть что внутри? Приходилось ли Вам МЕНЯТЬ содержимое этих таблиц (deflate-и3менение-inflate-3апись в ба3у)?
3. Константин Куликов (Светлый ум) 31.08.15 15:27
+1. Сложная и нужная тема
А подобные комментарии: (1)
"разобраться , как 1с8 сопоставляет реквизиты и поля бд. ", - уменьшаю неопределенность и говорят куда копать.
4. Михаил Максимов (МихаилМ) 31.08.15 17:33
(2) приходилось изменять dbnames. читайте мой комментарий к Вашей первой части про восстановление.
5. Михаил Беляев (METAL) 22.06.16 12:40
(4) МихаилМ, попробовал... Честно говоря, не понял как Вы меняли DBNames..
Ведь в указанной разработке http://infostart.ru/public/74406/ Deflate и чтение только делается
Inflate и запись - непонятно как...

Но Бог с ним, у меня даже на чтение не получается... (((

Тестовый скрипт Test.sql возвращает пустую таблицу.
Скрипт
SELECT * FROM [mybase].[dbo].[fn_GetBinary] (
(Select TOP 1 BinaryData From Config)) k
также возвращает пустую таблицу... :(

Возможно неправильно подключил?

Скрипты подключения во вложении (один вспомогательный просто разрешает выполнение CLR)

Можете подсказать, где я ошибся, и как всё-таки прочитать двоичные данные из SQL?

Прикрепленные файлы:
Разрешение исполнения CLR.sql
Подключение внешнего метода к SQL.sql
6. Михаил Максимов (МихаилМ) 28.06.16 17:56
(5) METAL,сейчас нет доступа к наработкам. поэтому ничем помочь не могу тк не помню . на инфостарте есть несколько аналогичных clr + исходники на си шапр.
попробуйте другую.
Например
7. Михаил Беляев (METAL) 08.07.16 08:56
(6) МихаилМ, спасибо! поискать по маске CLR я что-то не догадался.. Буду пробовать!
Для написания сообщения необходимо авторизоваться
Прикрепить файл
Дополнительные параметры ответа