Вступление
Был летний солнечный день и ничто не предвещало беды, когда зазвонил телефон и сотрудница на другом конце сообщила: "Похоже я убила базу клиента". После допроса с пристрастием выяснилось следующее: на обычном удаленном рабочем столе (RDP) проводилось обновление конфигурации с реструктуризацией базы, таких обновлений делается по тысячу пятьсот раз на дню. Однако, в этот раз пошло, что-то не так и база данных рухнула.
При повторном запуске программа выдавала сообщение
и после этого вываливалась в Windows. Наличие резервной копии позволило бы восстановить базу в два счета, но человеческая беспечноть сотрудницы, которая не потратила лишних пару минут для ее создания привела к тому, что исправление проблемы заняло около четырех дней, было сделано несколько неправильных шагов, которые не приводили к значимому результату. Ниже я описываю правильный путь.
Восстановление базы
Поиск по интернету привел к страницам с описанием данных проблем без наличия решения, однако вскоре были найдены две важные ссылки, которые явились отправной точной в восстановлении:
Краткое описание формата файлов *.1CD (файловых баз 1Сv8)
Восстанавливаем убитую базу 1C
Шаг №1. Делаем резервную копию испорченной базы
Коллега awa, упомянул в одном из сообщении, что штатная утилита 1С chdbfl.exe - чуть реже чем всегда бесполезна для исправления подобных проблем. Данная утилита проверяет только физическую целостность таблиц. Восстановление структур необходимых для запуска БД для нее непосильная задача. Более того, в некоторых случаях она портит испорченную базу на столько, что ее невозможно восстановить. В любом случае при запуске данной утилиты всегда делайте резервную копию базы.
Шаг №2. Делаем выгрузку конфигурации при помощи утилиты Tool_1CD
Утилита находится здесь: //infostart.ru/public/19633/
Помимо просмотра списка таблиц, там есть важная для нас функция выгрузки конфигурации. Запускаем утилиту, открываем базу. База открылась без сообщений об ошибок, это хороший знак!
Шаг №3. Анализируем структуру файла испорченной базы
Итак, как вам известно CD файл - это по сути хранилище файлов-таблиц. Открываем Hex редактор (например опенсорсный http://en.wikipedia.org/wiki/HxD), переходим по ссылке 0x4000. Тут находится таблица смещений основных таблиц базы данных и конфигурации.
Лирическое отступление
Все адреса хранятся в абсолютной адресации, что затрудняет исправление в ручном режиме, в случае если испортилась какая-то таблица не первая по списку. С другой стороны это упрощает программистам 1С работу и ускоряет процесс заргузки нужных таблиц в память.
Итак взглянем на таблицу из HEX редактора:
На этой картинке в левой части показан HEX редактор в правой части список таблиц из утилиты Tool_1CD. Их порядок совпадает с тем как они идут в файле CD. Здесь мы видим, что таблица CONFIG начинается с адреса 0x5000 и оканчивается на 0x31F0FFF, где следом начинается таблица CONFIGSAVE по адресу 0x31F1000 (для тех кто никогда не программировал на ассемблере скажу, что в машинных кодах числа пишутся с права на лево - пережиток царского режима). Строго говоря, 0x5000 расположен заголовок таблицы CONFIG, который ссылается еще на один заголовок, а потом уже следует сама таблица (см. описание формата файлов по ссылке выше). Разумно предположить, что если 1С ругается на конфигурацию, стало быть именно эту таблицу нам надо исправить, для этого надо выцепить таблицу CONFIG из сохраненной конфигурации (или если она не сохраняется, взять конфигурацию максимально близкой к испорченной) и подставить ее по адресу 0x5000, но при этом таблица не должна выходить за пределы 0x31F0FFF.
Upd 10/10/2012
Важное замечание awa:
1С обращается к таблицам по имени, и ей не важно, какая таблица находится в списке первой, какая второй и т.д. Просто при создании новой базы 1С создает нужные таблицы друг за другом в том порядке, в каком это создание написали программисты 1С. Поэтому всегда и получается, что CONFIG идет первой, CONFIGSAVE второй и т.д. Но если бы первой таблицей была бы какая-нибудь _REFERENCE152, а CONFIG была бы семнадцатой в списке, 1С спокойно бы работала с такой базой.
Шаг №4а. Загружаем в пустую конфигурацию выгруженную конфигурацию (извините за каламбур)
Загрузили. Записали. Смотрим в HEX-редакторе
Так-с, что-то не то, какая-то новая таблица добавилась. Отсюда вывод: Восстановление нужно делать на том же релизе платформы, что и испорченная база.
Шаг №5б. Загружаем в пустую конфигурацию выгруженную конфигурацию той же самой версии платформы
Смотрим результат:
Да-а, результат тоже не очень. Таблица CONFIG заканчивается по адресу 0x10FFF, судя по всему она не реструктуризирована. Ладно попробуем скопировать рабочую таблицу Tool_1CD в нерабочую базу. Выделяем блок в рабочей базе и копируем с замещением по адресу 0x5000 в испорченную базу:
Открываем Tool_1CD, открываем испорченную базу, но увы Tool_1CD виснет при попытке посмотреть таблицу CONFIG. После нескольких не правильных шагов, мне пришла идея: а что если 1С структурирует таблицы при загрузке базы? Тогда остается сделать выгрузку и загрузку базы с рабочей конфигурацией.
Шаг №5в. Загружаем в пустую конфигурацию выгруженную конфигурацию той же самой версии платформы, делаем выгрузку и загрузку базы (не конфигурации!).
Посмотрим как сейчас выглядят смещения:
Уже лучше. Теперь CONFIGSAVE расположена по адресу 0x31FC000, что больше чем 0x31F1000. Как же скопировать больший блок таблицы CONFIG в рабочей базе на меньший блок в испорченной базе? Ответ прост: надо удалить метаданные в рабочей конфигурации, не влияющие на ее структуру: общие модули, картинки, отчеты, обработки и т.п. Нам важно запустить испорченную базу, конфигурацию мы потом восстановим.
Шаг 6. Итерация по удалению метаданных конфигурации, не влияющие на ее структуру, выгрузка и загрузка базы.
После нескольких итераций удаления, выгрузки и загрузки базы, я получил следующую картину:
Наконец-то: CONFIGSAVE начинается с 0x313B0000<0x31F1000. Теперь выделяем блок 0x5000-x313AFFF в рабочей базе и в адрес 0x5000 в испорченной базы копируем с замещением
Записываем. Открываем 1С. Отклично, все заработало.
Upd 10/10/2012
Важное замечание awa
Как правило по смещению 0x4000, содержатся ссылки на файлы описания таблиц. А уже в файлах описания таблиц содержатся ссылки на таблицы записей, индексов и BLOB. В общем случае, если таблица CONFIG "начинается" с адреса 0x5000, а таблица CONFIGSAVE с адреса 0x31f1000 и нет никакой гарантии, что на промежутке от 0x5000 до 0x31f1000 не содержится ни одного блока, относящегося к любой другой таблице, помимо CONFIG. В большинстве случаев таблица CONFIG не фрагментирована, объясняется это, думаю, тем, что такое расположение файлов одной таблицы друг за другом, так, что вся таблица как бы находится в файле 1CD одним непрерывным куском, образуется в результате применения сжатия базы данных при тестировании и исправлении или при применении утилиты chdbfl.exe.
Осталось только загрузить в базу рабочую конфигурацию, чтобы восстановить рабочую базу. Все, База восстановлена.
P.S. Разумеется данный случай описывает исправление простых поломок, однако даже такой простой случай может ставить в тупик опытных профессионалов, когда не существует типовых способов решения проблемы. Не забывайте делать резерные копии.