Сигнатура не равна 1cdbmsv8 как исправить

9 г. назад

Восстановление работоспособности разрушенной файловой базы.

Этап 0. Введение в проблематику.

С упрямой периодичностью на форумах по 1С появляются крики души «Помогите! Упала файловая база, бэкапов нет, что делать?». Лично я всегда при этом вспоминаю известную шутку «Админы делятся на два типа — тех, кто делает бэкапы, и тех, кто будет их делать». Но, отбросив шутки в сторону, постараемся серьёзно рассмотреть данную проблему, ведь ситуации бывают разные. Например, бэкапы делались на диск, на котором закончилось место, или бэкапы делались через выгрузку, и все такие выгрузки за последнее время оказались неработоспособны. К слову сказать, даже админы, считающие себя «бывалыми», прокалываются на подобных мелочах.

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

1. Помимо настроенных автоматических ежедневных бэкапов, обязательно сделайте дополнительный бэкап перед такими критическими операциями, как обновление конфигурации, ТиИ, проверка базу с помощью chdbfl.exe и т.п.
2. Делайте бэкап архивированием (копированием) файла 1Cv8.1CD, либо комбинируйте копирование с выгрузкой в .dt. Ни в коем случае не ограничивайте бэкап только выгрузкой в .dt, ведь наличие некоторых ошибок в файле 1Cv8.1CD может привести к тому, что в выгрузке будет отсутствовать часть информации, либо выгрузку вообще невозможно будет загрузить. И если с 1Cv8.1CD можно «поколдовать» и попытаться выудить нужные данные, то в случае полностью отсутствующих данных уже ничего не сделаешь.
3. Процедуру создания бэкапа выполняйте в такой период, когда с базой не работают пользователи.
4. Периодически проверяйте наличие свободного места на устройстве, куда настроено автоматическое создание бэкапов.
5. Старайтесь размещать бэкапы не на том же компьютере, где расположена сама база, а на других компьютерах/хранилищах в локальной сети (например, если на компьютере испортится жёсткий диск, или проникнет вирус-шифровальщик, получим порушенные и базу, и бэкапы). Старайтесь также периодически размещать бэкапы на дополнительных (альтернативных) источниках, например, в облачном хранилище (dropbox, yandex disk и т.п.), или на флэшке.

Но что же делать, если самое страшное уже произошло, и база разрушилась, а рабочих бэкапов нет, или они очень старые?
Сразу оговорюсь, что не очень сложные случаи (например, когда база в режиме Предприятия работает нормально, а войти невозможно только в Конфигуратор, или наоборот, или проблема возникает только под определёнными пользователями) рассматривать не буду, т.к. в Интернете есть масса советов по решению подобных проблем — от очистки кэша и «перезаливки» конфигурации, до обновления версии платформы и выгрузки всех данных в чистую базу. Буду рассматривать самые сложные случаи, когда в базу невозможно зайти ни в режиме Предприятия, ни в режиме Конфигуратора ни под одним из пользователей. Симптомы при этом могут быть разные: 1С «зависает» при попытке войти в базу, либо выдаёт сообщения типа «Ошибка формата потока», «База данных полностью разрушена», «Файл базы данных поврежден», «При обновлении данных, после последней реструктуризации, произошла критическая ошибка», «Обнаружена незавершенная операция сохранения конфигурации», либо «падает» с сообщением об ошибке приложения от операционной системы.
image1.png

Первоначальные действия для диагностирования таких случаев должны быть такими:

1. Обязательно делаем самый первоначальный бэкап нашей проблемной базы (до любых манипуляций с ней) копированием/архивированием файла 1Cv8.1CD, и убираем его в надёжное место, дабы случайно не повредить.
2. Пробуем войти в базу под другими пользователями.
3. Полностью очищаем кэш 1С (это можно сделать, например, простым удалением базы из списка, и добавлением её в список вновь, либо использовать утилиты типа http://infostart.ru/public/90572/ , либо удалить вручную http://help1c.com/faq/view/1267.html ).
4. Пробуем перенести файл базы на другой компьютер, и войти в базу там.
5. Прибегаем к помощи утилиты chdbfl.exe из поставки 1С:Предприятие, с установленной галкой «Исправлять обнаруженные ошибки».
6. Ещё можно попробовать открыть базу на более свежих релизах 1С, например, если работали на 8.2.15, то можно попробовать на 8.2.17.
image2.png

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

Итак, Вы решили починить базу своими руками, и окунуться в самые дебри загадочного содержимого файла 1Cv8.1CD. Какие же полезные статьи и инструменты мы имеем на текущий день?

1. Перво-наперво советую ознакомиться со статьями уважаемого awa http://infostart.ru/public/19734/ и http://infostart.ru/public/187832/ , содержащими описание формата файловой базы данных .1CD. Крайне настоятельно рекомендую прочитать, осмыслить, и отложить в памяти. Ведь без ясного представления устройства базы заниматься её ремонтом весьма проблематично.
2. Ещё есть официальная информация о предназначении некоторых таблиц БД от 1С: http://1c-dn.com/library/data_structure_in_1c_enterprise_8/?SECTION_CODE=data_structure_in_1c_enterprise_8&print=Y (к сожалению, только анголязычная).
3. Неофициальная информация о таблицах и полях: http://main.1c-ei.ru/Home/help/objectdb/dbschema (русскоязычная и более развёрнутая)
4. Далее, есть прекрасная утилита Tool_1CD http://infostart.ru/public/19633/ , позволяющая визуально просмотреть и извлечь данные из файла .1CD в xml-файлы, а также сохранить конфигурацию БД, основную конфигурацию и конфигурацию поставщика. Если из рухнувшей базы нужно спасти только конфигурацию — то самым лёгким и простым вариантом является именно она. Выгруженные в xml-файлы данные частично можно подгрузить в другую базу при помощи разработки http://infostart.ru/public/143704/ , однако поддерживается только определённый перечень объектов.
5. Система восстановления баз 1С restoration-base-1c8: http://code.google.com/p/restoration-base-1c8/downloads/list . Является конфигурацией для 1С, позволяющей загрузить и редактировать в ручном режиме содержимое файловой базы. Загрузка базы происходит очень долго, следует запастить терпением. Считывает блоки, не опираясь на данные корневого объекта, поэтому, если имеем базу с полностью разрушенным корневым объектом, то может быть весьма полезна. Описание примера применения: http://infostart.ru/public/158034/
6. Компонента 1CDLib для прямого чтения/записи данных из файлов баз данных .1CD http://infostart.ru/public/166557/ Компонента для прямого чтения/записи данных из файлов баз данных .1CD — инструмент, позволяющий не только читать данные из файловой базы, но и записывать. Данная компонента позволяет применять к файловым базам многие имеющиеся на просторах Интернета советы по ремонту клиент-серверных баз (MS SQL, PostgreSQL и т.д.), например: http://www.gilev.ru/1c/81/restore/ , http://infostart.ru/public/116123/ . Поскольку является внешней компонентой для 1С, позволяет в 90% случаев ремонтировать базы при помощи написания определённого кода (скрипта) на языке 1С после проведения процедуры обследования, не прибегая к hex-редактору.
7. Hex-редактор HxD http://mh-nexus.de/en/hxd/ (на случай, если что-то надо посмотреть или подправить непосредственно и в ручном режиме). В принципе, можно использовать любой, но мне понравился этот.
image3.png

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

Этап 1. Обследование, определение проблемных мест.

Итак, перед нами «мёртвая» файловая база. Задача, которая стоит перед нами на текущий момент — всесторонне обследовать базу, составить максимально полный перечень проблемных мест (ошибок). Одной из распространённых ошибок у начинающих специалистов является следующая: они либо сразу и надолго «ныряют» в содержимое файла базы в hex-редакторе, пытаясь вручную разобраться в тоннах байт, что, естественно, через некоторое время вызывает эффект отторжения, либо, попробовав один какой-нибудь инструмент, и получив неудачу, выдают заключение: «База не подлежит ремонту». Лично я считаю, что к услугам hex-редактора нужно прибегать только в исключительных случаях, либо изредка, на минутку, например, чтобы своими глазами посмотреть содержимое, находящееся по определённому смещению.
А перечень инструментов и приёмов для получения информации о проблемных местах вообще довольно широк, причём даже сама платформа 1С предоставляет, как минимум, два штатных способа. Рассмотрим их поподробнее.

1. Утилита chdbfl.exe из поставки 1С:Предприятие. Запускаем её с установленной галкой «Исправлять обнаруженные ошибки».
image5.png
Сразу хочу оговориться, что на данном этапе эта утилита будет использоваться нами исключительно для диагностики, поэтому, даже если она и выдаст нам какой-то изменённый, якобы отремонтированный файл базы, мы не имеем на него каких-то видов, и просто «выкидываем». Однако, внимательно изучаем протокол работы и фиксируем перечень ошибок, найденных этой утилитой.
Например, «Поврежден заголовок файла базы данных» чаще всего означает просто некорректно записанную в нём длину файла в блоках, а не полное его разрушение (чтобы в этом убедиться, достаточно на пару секунд обратиться к hex-просмотрщику или редактору, если в начале файла сигнатура 1CDBMSV8 на месте, значит, проблема только в поле длины). «Повреждено содержимое внутреннего файла » означает, что в корневом объекте существуют «битые записи», с некорректными номерами блоков заголовков, либо с испорченными блоками заголовков. И так далее.

2. Технологический журнал (ТЖ) 1С:Предприятие. Прекрасная возможность узнать, на каком месте «спотыкается» платформа, если она «зависает», «падает», или выдаёт загадочное сообщение «Ошибка формата потока» (причём сама ошибка может быть где угодно, в любом из файлов системных таблиц). Закрываем все сеансы 1С, чтобы они нам не мешались, и настраиваем запись ТЖ. Для этого идём в папку «bin», где лежат исполняемые файлы текущей плафтормы «1cv8*.exe», находим там вложенную папку «conf», и создаём там файл настройки записи ТЖ «logcfg.xml» примерно следующего содержания (исходный текст файла настройки есть в прикреплённом архиве):
image4.png

Вместо «C:1cv8logs» можно указать любую существующую папку, куда будут писаться логи, но лучше создать новую, пустую, чтобы не было проблем с записью логов.
(Подробнее про настройку ТЖ можно почитать, например, здесь: http://help1c.com/faq/view/464.html )
Далее, запускаем нашу проблемную базу в режиме конфигуратора, дожидаемся вывода окошка с ошибкой, или краха приложения, и сразу же идём изучать содержимое записанного лога (он будет в файле «1cv8_PIDМеткаДаты.log»). На следующие события и ошибки не обращаем внимания (их наличие является нормальным):

Exception=NetDataExchangeException,Descr='server_addr=any:port_num descr=Ошибка сетевого доступа к серверу...
Exception=DatabaseException8,Descr="Отсутствует файл базы данных 'ПутьКБазе/1Cv8tmp.1CD'"
Файл не обнаружен 'SprScndInfo'

и некоторые другие.
Собственно, мы даже можем не увидеть там нужного нам сообщения об ошибке, но зато мы увидим, при работе с каким объектом (таблицей или внутренним файлом таблицы) происходит ошибка.
image1.png

1С:Предприятие начинает загрузку базы с чтения содержимого системных таблиц. Системными таблицами являются:
V8USERS — таблица с данными пользователей (для баз версий 8.2 и выше)
DBSCHEMA — схема (структура) БД
_USERSWORKHISTORY — история работы пользователей
_COMMONSETTINGS, _FRMDTSETTINGS, _REPSETTINGS, _REPVARSETTINGS, _SYSTEMSETTINGS — хранилища различных настроек
а также системные таблицы-каталоги:
PARAMS — содержит файлы с параметрами БД
FILES — содержит прочие системные (служебные) файлы
CONFIG — содержит файлы конфигурации БД. Здесь же, в файлах с названиями вида GUID.GUID хранятся конфигурации поставщика (отсутствие таковых является нормальной ситуацией, означающей, что либо конфигурация полностью совпадает с типовой (не включен режим изменения), либо она снята с поддержки, либо является самописной).
CONFIGSAVE — содержит файлы основной конфигурации. Отсутствие записей в ней является нормальной ситуацией, означающей, что основная конфигурация полностью совпадает с конфигурацией БД. Стоит отметить, что здесь могут содержаться не все файлы конфигурации, а только изменённые (отличающиеся от файлов конфигурации БД).
Системные таблицы-каталоги являются, по сути, аналогами каталога в обычной файловой системе, т.е. являются хранилищем некоторого набора файлов, и имеют следующие поля:
FILENAME — имя файла
CREATION/MODIFIED — дата создания/изменения
ATTRIBUTES — атрибуты
DATASIZE — размер файла
BINARYDATA — содержимое файла (двоичные данные)

В случае полного отсутствия какой-либо системной таблицы (не путать с наличием пустой таблицы) 1С при старте базы выдаст сообщение «База данных полностью разрушена».

Теперь мы понимаем, что записи в ТЖ типа

22:42.0169-1,DBV8DBEng,2,process=1cv8,Trans=0,Func=selectFileName,FileName=ibparams.inf
22:42.0170-3,DBV8DBEng,1,process=1cv8,Trans=0,Func=readFile,CatName=Params,FileName=ibparams.inf

означают чтение файла «ibparams.inf» из таблицы PARAMS.

Итак, анализируем файл лога. Например, если происходит «Ошибка формата потока», а в конце файла лога мы видим примерно следующее:

41:29.3460-1,DBV8DBEng,2,process=1cv8,Usr=Админ,Trans=0,Func=restoreObject,tableName=DBChanges
41:29.3900-439,DBV8DBEng,2,process=1cv8,Usr=Админ,Trans=0,Func=restoreObject,tableName=DBSchema
41:29.3901-443,SDBL,1,process=1cv8,Usr=Админ,Trans=0,Sdbl=GET NGENERATIONS
41:29.4060-19207,SESN,1,process=1cv8,Func=Attach,IB=ПутьКБазе,Nmb=2,ID=GUID
41:29.4061-19210,SESN,1,process=1cv8,Func=Finish,IB=ПутьКБазе,Nmb=2,ID=GUID

то можно заключить, что ошибка формата потока возникла при работе с содержимым таблицы «DBSchema», следовательно, содержимое этой таблицы нужно будет изучить поподробнее.
Ещё, если в наличии есть какой-нибудь старый бэкап, можно применить такой приём: записать ТЖ при его старте, и сравнить его с ТЖ при старте проблемной базы, чтобы понять, какими сообщениями об исключениях можно пренебречь, а также, какие этапы при старте проблемной базы проходят нормально, а до каких дело не доходит.
По окончании данной процедуры файл «logcfg.xml» можно переименовать, чтобы не засорять ненужными логами диск.

3. Открываем нашу базу при помощи утилиты Tool_1CD. Здесь мы можем просмотреть таблицы, а также их содержимое (данные записей), причём для системных таблиц (DBSCHEMA, PARAMS и т.д.) поддерживается автоматическая распаковка содержимого BLOB-полей, вплоть до показа содержимого упакованных контейнеров (в таблицах CONFIG и CONFIGSAVE). Наиболее пристальное внимание уделяем тем проблемным объектам, которые были нами найдены по результатам действий из пунктов 1 и 2, а также системным таблицам (хотя, зачастую список проблемных объектов, составленный по п. 1 и 2, ограничивается именно системными таблицами).
image2.png
При просмотре перечня таблиц смотрим, есть ли таблицы с окончаниями «OG» — их наличие означает, что крах базы произошёл при ТиИ или реструктуризации (в процессе выполнения этих операций 1С создаёт новые таблицы с такими окончаниями, куда пишутся данные реструктуризованных таблиц, затем исходная таблица удаляется, а новой назначается исходное имя). Также бывает полезно сравнить перечень таблиц с содержимым старого бэкапа (при его наличии, и при условии, что конфигурация не обновлялась, иначе состав таблиц, связанных с метаданными, конечно, будет различаться), это поможет выявить отсутствующие таблицы.
При просмотре таблицы CONFIG обращаем внимание, есть ли в ней файлы с окончаниями «.new» — их наличие означает, что крах базы произошёл при обновлении конфигурации БД.
Также утилита позволяет сохранить конфигурацию БД в cf-файл, что и рекомендуется сделать. Загружаем далее эту конфигурацию из файла в пустую базу, и пробуем запустить. Если всё запустилось успешно, значит, проблема нашей базы не в конфигурации.

4. Открываем базу при помощи компоненты 1CDLib. Информация из п. 3 в полной мере относится и к этому пункту, меняется только методика работы с файлом базы — посредством скриптов, использующих функции компоненты, с последующим анализом лог-файла и извлечённых данных.
Вашему вниманию представлены два скрипта (являющихся внешними обработками для режима управляемого приложения 1С:Предприятие 8.2, их можно запустить, например, из созданной пустой базы), с помощью которых можно произвести полуавтоматическое обследование проблемной базы:
Обработка «SaveAllTables.epf» позволяет сохранить данные всех таблиц в виде структуры вложенных папок и файлов в папке «Objects» (создаётся там же, где находится файл базы), и далее их можно изучать при помощи обычного файлового менеджера. Также, после сохранения всех таблиц, полезно изучить содержимое лога «logdb1cd.log» — туда выводятся сообщения об ошибках, которые произошли при извлечении таблиц. Если сообщения об ошибках в нём отсутствуют, то можно сказать, что физических ошибок в структуре хранения таблиц в файле базы нет, и проблемы уже либо в отсутствии каких-то таблиц, либо в их некорректном содержимом.
Обработка «ViewRecords.epf» позволяет просматривать записи таблиц и сохранять в файлы BLOB-данные (файлы создаются в папках с именами соответствующих таблиц), предназначена, в первую очередь, для полуавтоматического анализа содержимого системных таблиц (хотя с помощью неё можно просмотреть и другие таблицы). В случае ошибок при извлечении BLOB-данных, или при их распаковке (если содержимым BLOB-поля являются запакованные по алгоритму Deflate данные), выводятся соответствующие сообщения.
image3.png

5. Загрузка базы в систему восстановления баз 1С restoration-base-1c8. По состоянию дел на текущий момент, в данном продукте многие функции не реализованы, а некоторые, на мой взгляд, реализованы не совсем прозрачно. Кроме того, практически вся смысловая обработка данных происходит на стороне 1С, что далеко не лучшим образом сказывается на быстродействии. Например, у меня полная загрузка файла размером 230 Мб длилась около часа, за это время я уже всесторонне обследовал базу другими инструментами, и приступил к непосредственному ремонту. Окончания же загрузки файла размером 1,5 Гб я вообще не дождался — закончилось терпение. Ещё один нюанс: поскольку система является конфигурацией для 1С, то все данные исходной базы загружаются также в базу 1С, но оказываются они в табличной части одного справочника. Следовательно, даже не принимая во внимание скорость загрузки, в случае файловой базы не получится загрузить файл с исходной базой размером более 4 Гб (из-за ограничений формата). Тем не менее, проект является свободным, с открытым кодом, доступным для изменения и доработки, поэтому не могу не упомянуть про него.

Загрузив нашу базу в систему restoration-base-1c8, мы можем исследовать список таблиц:
image6.png
а также просмотреть и отредактировать данные любого блока во встроенном hex-редакторе:
image7.png
Просмотр записей таблиц, к сожалению, не реализован.

На этом наш список, а также сам этап обследования заканчивается. Аккуратно фиксируем и систематизируем всю собранную информацию, которую мы будем использовать далее, в процессе «лечения». Конкретные, наиболее типичные проблемные ситуации и способы их устранения будут рассмотрены в следующих разделах.

Файлы:
Обработки с поддержкой формата БД 8.3.8:
Обработки для обследования.zip

Этап 2. Лечим базу.

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

В общем виде, скрипт выглядит так:

    FileDB=Новый("AddIn.T1CDLib.DB1CD");
    FileDB.OpenLogFile(ИмяЛога);
    Состояние("Чтение структуры файла");
    FileDB.Open1CDFile(ИмяФайла);
    Состояние("Обработка файла");

    // здесь выполняем различные операции по лечению базы

    FileDB.CloseFile();
    FileDB.CloseLogFile();

    Состояние("");

В зависимости от списка проблем, составленного на этапе обследования, можно выполнить различные операции:
1. Если в заголовке базы указан неверный размер, то исправляем заголовок:

    FileDB.FixMainStreamHeader();

2. Если есть таблицы с некорректным размером одного или нескольких объектов (описание, записи, BLOB, индексы):

    FileDB.FixTableHeaders("TABNAME",Истина,Истина,Истина,Истина);

В моей практике бывали случаи, что chdbfl.exe при некорректном размере объектов какой-то таблицы не мог восстановить добрую половину данных этой таблицы, а вот после исправления размеров «терял» буквально пару-тройку записей, и это безо всякого изменения содержимого объектов такой таблицы.
3. Если есть некорректные записи в корневом объекте RootEntry:
Вывести содержимое корневого объекта в лог-файл можно так:

    FileDB.PrintRootEntry();

Удалить некорректную запись по индексу (нумерация — с 1) из корневого объекта:

FileDB.DeleteTableFromRootEntry(ИндексЗаписи);

Если содержимое какой-то потерянной таблицы нашлось в недрах файла БД (например, при помощи поиска в Hex-редакторе), но ссылка на неё отсутствует в корневом объекте, можно её добавить:

    FileDB.AddTableToRootEntry(ИндексБлокаЗаголовкаОписанияТаблицы);

Внимание: после манипуляций с корневым объектом нужно переоткрыть БД:

    FileDB.CloseFile();
    FileDB.Open1CDFile(ИмяФайла);

4. Если в перечне таблиц базы есть таблицы с окончаниями «OG», это означает, что база рухнула в процессе реструктуризации или ТиИ. В данном случае может помочь такая операция (удаление окончания из имени таблиц):

    ArrayPres=FileDB.GetTablesArray(Ложь);
    TablesArray=РазвернутьЗначение(ArrayPres);

    Для TabInd=1 По TablesArray.Count() Цикл
        TableInfo=TablesArray[TabInd-1];
        TableName=TableInfo.Name;
        Если ВРег(Прав(TableName,2))="OG" Тогда
            МасПереимТаб.Добавить(TableName);
        КонецЕсли;

    КонецЦикла;

    Состояние("Переименование таблиц");

    Для каждого ТекТаб из МасПереимТаб Цикл
        FileDB.RenameTable(ТекТаб,Лев(ТекТаб,СтрДлина(ТекТаб)-2));
    КонецЦикла;

Однако, надо понимать, что содержимое таких таблиц может не соответствовать текущей конфигурации БД. В случае ТиИ вероятность несоответствия невысока, а вот при прерванном обновлении может быть по-разному, но, в любом случае, попробовать стоит.

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

    МасПереносТаб=Новый Массив;
    МасПереносТаб.Добавить("Reference19");
    МасПереносТаб.Добавить("Document192");

    ПапкаБазы="ПутьКПроблемнойБазе";
    ПапкаБазыПред="ПутьКБазеИзБэкапа";
    ИмяФайла=ПапкаБазы+"1Cv8.1CD";
    ИмяФайлаПред=ПапкаБазыПред+"1Cv8.1CD";

    FileDB=Новый("AddIn.T1CDLib.DB1CD");
    Состояние("Чтение структуры файла");
    FileDB.Open1CDFile(ИмяФайла);

    FileDB2=Новый("AddIn.T1CDLib.DB1CD2");
    FileDB2.Open1CDFile(ИмяФайлаПред);

    Состояние("Перенос таблиц");

    Для каждого ТекТаб из МасПереносТаб Цикл
        TableName=ТекТаб;
        ПапкаТаб=ПапкаБазыПред+TableName+"";
        ВремКат=Новый Файл(ПапкаТаб);
        Если (НЕ ВремКат.Существует()) Тогда
            СоздатьКаталог(ПапкаТаб);
        КонецЕсли;

        FileNameDescription=ПапкаТаб+"Description";
        FileNameRecords=ПапкаТаб+"Records";
        FileNameBLOB=ПапкаТаб+"BLOB";
        FileNameIndexes=ПапкаТаб+"Indexes";

        FileDB2.SaveTableDataToFile(TableName,FileNameDescription,FileNameRecords,FileNameBLOB,FileNameIndexes);

        FileDB.LoadTableDataFromFile(TableName,FileNameDescription,FileNameRecords,FileNameBLOB,FileNameIndexes);
    КонецЦикла;

    FileDB.CloseFile();

    FileDB2.CloseFile();

Естественно, ссылки на элементы этих таблиц, созданные после бэкапа, будут «битыми», однако это всё же лучше, чем ничего.

Нумерация пунктов соответствует рекомендуемому порядку операций: т.е., сначала нужно исправить заголовки базы и таблиц, затем «разобраться» с корневым объектом, а затем уже приступать к манипуляциям с таблицами.

Также нужно помнить, что после всех проделанных манипуляций очеь полезно «шлифануть» базу утилитой chdbfl.exe с установленной галкой «Исправлять обнаруженные ошибки». Эта процедура перепакует данные всех таблиц, избавив их от мусора и удалённых записей, а также полностью перестроит индексы (а из-за «протухших» индексов база может по-прежнему не запускаться ни в одном из режимов, хотя сами данные могут быть уже восстановлены полностью).

В следующем разделе будут рассмотрены различные ситуации при наличии проблем в конфигурации (таблицах CONFIG и CONFIGSAVE).

Этап 3. Лечим конфигурацию.

Проблемы в таблицах конфигурации — одна из самых частых причин «падения» файловой БД. Последствия бывают как лёгкие (невозможность открытия определённых объектов в режиме Предприятия и/или Конфигуратора, обновления конфигурации), так и тяжёлые (невозможность открытия БД ни в режиме Предприятия, ни в режиме Конфигуратора).

Как мы помним, конфигурация хранится в двух таблицах: CONFIG — содержит файлы конфигурации БД, CONFIGSAVE — содержит файлы основной (сохранённой, редактируемой) конфигурации. Если на этапе обследования были выявлены проблемы в этих таблицах («битые» записи/файлы, существенно меньшее количество файлов по сравнению с типовой конфигурацией или конфигурацией из последнего бэкапа (это не касается таблицы CONFIGSAVE, т.к. для неё уменьшение количества записей может являться нормальной ситуацией, означающей, что изменения из основной конфигурации перенесли в конфигурацию БД), наличие файлов с окончаниями «.new» в имени, и пр.), то пора приступать к их лечению (для этого прибегнем к помощи компоненты 1CDLib).

Начнём с лёгкого — таблицы CONFIGSAVE. Поскольку утеря содержимого этой таблицы не очень страшна (будут лишь утеряны сохранённые, но не перенесённые в БД изменения конфигурации), то самым кардинальным способом является полная очистка содержимого данной таблицы:

    FileDB=Новый("AddIn.T1CDLib.DB1CD");
    Состояние("Чтение структуры файла");
    FileDB.Open1CDFile(ИмяФайла);

    FileDB.OpenTable(0,"CONFIGSAVE");
    FieldFileName="FILENAME";

    Состояние("Перебор записей");
    Рез=FileDB.MoveFirstRecord(0);
    Пока Рез Цикл
        Если НЕ FileDB.IsRecordDeleted(0) Тогда
            FileDB.DeleteRecord(0);
        КонецЕсли;

        Рез=FileDB.MoveNextRecord(0);
    КонецЦикла;

    FileDB.CloseFile();

В результате основная конфигурация будет приведена к конфигурации БД.

Также можно попытаться перенести данные этой таблицы из последнего бэкапа, но только в том случае, если с момента бэкапа изменения не переносились в конфигурацию БД. Хочется отметить, что вероятность наличия такого бэкапа ничтожно мала, но, всё-таки, отметим эту возможность.

Теперь перейдём к таблице CONFIG. Если содержимое этой таблицы сильно повреждено, пути восстановления следующие:
1.Если есть бэкап, с момента которого изменения в конфигурацию БД не вносились, или вносились незначительные изменения, не повлёкшие за собой реструктуризацию БД, то самый простой путь — перенести данные этой таблицы из бэкапа:

    МасПереносТаб=Новый Массив;
    МасПереносТаб.Добавить("CONFIG");

    ПапкаБазы="ПутьКПроблемнойБазе";
    ПапкаБазыПред="ПутьКБазеИзБэкапа";
    ИмяФайла=ПапкаБазы+"1Cv8.1CD";
    ИмяФайлаПред=ПапкаБазыПред+"1Cv8.1CD";

    FileDB=Новый("AddIn.T1CDLib.DB1CD");
    Состояние("Чтение структуры файла");
    FileDB.Open1CDFile(ИмяФайла);

    FileDB2=Новый("AddIn.T1CDLib.DB1CD2");
    FileDB2.Open1CDFile(ИмяФайлаПред);

    Состояние("Перенос таблиц");

    Для каждого ТекТаб из МасПереносТаб Цикл
        TableName=ТекТаб;
        ПапкаТаб=ПапкаБазыПред+TableName+"";
        ВремКат=Новый Файл(ПапкаТаб);
        Если (НЕ ВремКат.Существует()) Тогда
            СоздатьКаталог(ПапкаТаб);
        КонецЕсли;

        FileNameDescription=ПапкаТаб+"Description";
        FileNameRecords=ПапкаТаб+"Records";
        FileNameBLOB=ПапкаТаб+"BLOB";
        FileNameIndexes=ПапкаТаб+"Indexes";

        FileDB2.SaveTableDataToFile(TableName,FileNameDescription,FileNameRecords,FileNameBLOB,FileNameIndexes);

        FileDB.LoadTableDataFromFile(TableName,FileNameDescription,FileNameRecords,FileNameBLOB,FileNameIndexes);
    КонецЦикла;

    FileDB.CloseFile();

    FileDB2.CloseFile();

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

2. Если конфигурация является полностью типовой, либо типовой с незначительными изменениями, не повлёкшими за собой реструктуризацию БД, и которыми можно пренебречь, то можно перенести конфигурацию из развёрнутой новой базы с типовой конфигурацией. Но здесь есть одна проблемка — как точно узнать нужный релиз, если база не открывается ни в одном режиме? Выход есть: открываем декомпрессированное содержимое файла «root» — там мы увидим GUID нужного нам файла (например, для БП 2.0 это «e0666db2-45d6-49b4-a200-061c6ba7d569»), далее открываем декомпрессированное содержимое этого файла — там, недалеко от начала файла, мы увидим название конфигурации, редакцию, название и копирайты разработчика, и, что самое важное, номер релиза.
Скрин1.png
Далее — дело техники, нужно найти нужный релиз типовой конфигурции и перенести содержимое таблицы CONFIG в нашу проблемную базу. (Извлечь содержимое таблицы CONFIG можно при помощи обработки ViewRecords.epf из 1. Обследование.)

3.Если база рухнула во время обновления конфигурации БД (характерным признаком этого является наличие файлов с окончаниями «.new» в имени), то может помочь вот такой скрипт (удаляет файлы с окончаниями «.new»):

    FileDB=Новый("AddIn.T1CDLib.DB1CD");
    Состояние("Чтение структуры файла");
    FileDB.Open1CDFile(ИмяФайла);

    FileDB.OpenTable(0,"CONFIG");
    FieldFileName="FILENAME";

    Состояние("Перебор записей");
    Рез=FileDB.MoveFirstRecord(0);
    Пока Рез Цикл
        Если НЕ FileDB.IsRecordDeleted(0) Тогда
            FileName=FileDB.ReadSimpleValue(0,FieldFileName);
            Если (Прав(FileName,4)=".new") Тогда
                FileDB.DeleteRecord(0);
            КонецЕсли;
        КонецЕсли;

        Рез=FileDB.MoveNextRecord(0);
    КонецЦикла;

    FileDB.CloseFile();

В данной статье приведены наиболее типичные скрипты. Путей восстановления конфигурации, конечно, намного больше, можно написать любой скрипт с использованием функций компоненты 1CDLib — переименование, удаление файлов по определённым условиям, перенос определённых файлов из другой базы, и т.д.
Например, рецепты восстановления клиент-серверных БД типа http://infostart.ru/public/138797/ (приведён рецепт лечения после неудачного динамического обновления) легко и непринуждённо можно применять и для файловых баз, причём безо всяких лазаний в дебрях файла БД с Hex-редакторами и прочими «напильниками».
Сравните, например, шаманские танцы с бубном в http://infostart.ru/public/154556/ , которые ещё и не всегда могут увенчаться успехом, и простенький скрипт

    FileDB.OpenTable(0,"CONFIG");
    FieldFileName="FILENAME";

    Состояние("Перебор записей");
    Рез=FileDB.MoveFirstRecord(0);
    Пока Рез Цикл
        Если НЕ FileDB.IsRecordDeleted(0) Тогда
            FileName=FileDB.ReadSimpleValue(0,FieldFileName);
            Если (FileName="сommit") ИЛИ (FileName="dbStruFinal") Тогда
                FileDB.DeleteRecord(0);
            КонецЕсли;
        КонецЕсли;

        Рез=FileDB.MoveNextRecord(0);
    КонецЦикла;


Надеюсь, что данная статья поможет Вам в восстановлении базы, но ещё лучше не забывать про ежедневные бэкапы.

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

Pick a username
Email Address
Password

By clicking “Sign up for GitHub”, you agree to our terms of service and
privacy statement. We’ll occasionally send you account related emails.

Already on GitHub?
Sign in
to your account

Здравствуйте. ситуация такова, не знаю как была, база, в ней вроде работали, щас она не открывается говорят. 1С пишет следующее: Ошибка при выполнении операции с информационной базой Файл не является файлом базы данных ‘D:Food1/1Cv8.1CD’ по причине: Файл не является файлом базы данных ‘D:Food1/1Cv8.1CD’ Далее chdbfl.exe пишет следующее: Поврежден заголовок файла базы данных Повреждено содержимое внутреннего файла <Описание базы данных> Далее читая форумы нашел обработку TOOL_1CD (правда не понимаю, она правит и тестированием решает ошибки или просто информатор),но пишет следующее: Файл не является базой 1С (сигнатура не равна «1CDBMSV8»). Свято верю, что базу данных можно восстановить файл, тока не знаю как в Блоке 0, указать это сигнатуру, как туда залеть и попробывать. Знаю суббота тяжкое время, но надеюсь будут советы.

Можно было 100%. Сейчас ты поковырялся 60%. Поковыряйся есще и восстановить будет или дорого или невозможно.

если свято верите то пишите он — автор  TOOL_1CD.

копия есть, но я не ковырялся, тока пробывал открыть.

Совет обычный. До того как сделать шаг один, сделать копию диска одной из сотни программ.  Acronis Recovery, R-Studio, GetDataBack, EasyRecovery.

немного не понял, что вы имеете виду.

Во-первых, заголовок файла так просто не слетает. То есть должны быть какие-то причины. Во-вторых, если файл разрушен, то есть вероятность, что куски файла остались в других местах диска — если продолжить работу на данном диске, то очень велика вероятность, что они будут разрушены. В-третьих, возможно, что файл был зашифрован вирусом — тогда нужно не потерять сам вирус, так как внутри него находится ключ шифрования.

>> тогда нужно не потерять сам вирус, так как внутри него находится ключ шифрования. На двору 2013 год. Лето. Вирусов который шифруюе файлы и остаются в системе не осталось. Закон Дарвина их вывел за обочину.

У ТС не вирус на 95%. А издохлый винт. Поэтому в первую очередь нужно его образ сеять на рабочий.  И дальше с образом работать.

Любой троян, шифрующий файлы из инета загружает своё тело, которое частенько в кеше браузера и остаётся.

Я больше за «неожиданное» отключение питания.

Вы наверно отстали от реальности.

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

Тэги: 1С 8

Комментарии доступны только авторизированным пользователям

Я
   Sun125

04.09.13 — 08:39

Полетел сервер с базой 1С, база повреждена. Пытаюсь полечить через chdbfl.exe, пишет:

Поврежден заголовок файла базы данных

Поврежден заголовок внутреннего файла <Описание базы данных>

Что-нибудь можно еще предпринять? база очень нужна, копии нет

   vde69

Модератор

1 — 04.09.13 — 08:40

http://code.google.com/p/restoration-base-1c8/wiki/OtherLink

   МихаилМ

2 — 04.09.13 — 09:21

выгрузить загрузить с помощью tool_1cd.

естественно, что выгрузиться.

если повреждение данных обширно и выгружается не достаточно для восстановления данных

обратиться к автору tool_1cd. он ,возможно, сможет сделать чудо.

   dk

3 — 04.09.13 — 09:26

фирма 1с тоже вроде как лечить базы могет

   Sun125

4 — 04.09.13 — 10:09

(2) tool_1cd пишет: база не явлется базой 1С. Сигнатура не равна «1CDBMSV8». В файле действительно нет в начале «1CDBMSV8»

   МихаилМ

5 — 04.09.13 — 10:18

(4)

тогда только вам поиогут

к vde69, awa15,andrewks и молитва

   Sun125

6 — 04.09.13 — 10:20

(5) а если в hex-редакторе прописать «1CDBMSV8», это может помочь?

  

МихаилМ

7 — 04.09.13 — 11:40

(6)

маловероятно.

нужно знать формат таблиц.

тогда можно их попробовать вытащить.

TurboConf — расширение возможностей Конфигуратора 1С

8 г. назад

Восстановление работоспособности разрушенной файловой базы.

Этап 0. Введение в проблематику.

С упрямой периодичностью на форумах по 1С появляются крики души «Помогите! Упала файловая база, бэкапов нет, что делать?». Лично я всегда при этом вспоминаю известную шутку «Админы делятся на два типа — тех, кто делает бэкапы, и тех, кто будет их делать». Но, отбросив шутки в сторону, постараемся серьёзно рассмотреть данную проблему, ведь ситуации бывают разные. Например, бэкапы делались на диск, на котором закончилось место, или бэкапы делались через выгрузку, и все такие выгрузки за последнее время оказались неработоспособны. К слову сказать, даже админы, считающие себя «бывалыми», прокалываются на подобных мелочах.

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

1. Помимо настроенных автоматических ежедневных бэкапов, обязательно сделайте дополнительный бэкап перед такими критическими операциями, как обновление конфигурации, ТиИ, проверка базу с помощью chdbfl.exe и т.п.
2. Делайте бэкап архивированием (копированием) файла 1Cv8.1CD, либо комбинируйте копирование с выгрузкой в .dt. Ни в коем случае не ограничивайте бэкап только выгрузкой в .dt, ведь наличие некоторых ошибок в файле 1Cv8.1CD может привести к тому, что в выгрузке будет отсутствовать часть информации, либо выгрузку вообще невозможно будет загрузить. И если с 1Cv8.1CD можно «поколдовать» и попытаться выудить нужные данные, то в случае полностью отсутствующих данных уже ничего не сделаешь.
3. Процедуру создания бэкапа выполняйте в такой период, когда с базой не работают пользователи.
4. Периодически проверяйте наличие свободного места на устройстве, куда настроено автоматическое создание бэкапов.
5. Старайтесь размещать бэкапы не на том же компьютере, где расположена сама база, а на других компьютерах/хранилищах в локальной сети (например, если на компьютере испортится жёсткий диск, или проникнет вирус-шифровальщик, получим порушенные и базу, и бэкапы). Старайтесь также периодически размещать бэкапы на дополнительных (альтернативных) источниках, например, в облачном хранилище (dropbox, yandex disk и т.п.), или на флэшке.

Но что же делать, если самое страшное уже произошло, и база разрушилась, а рабочих бэкапов нет, или они очень старые?
Сразу оговорюсь, что не очень сложные случаи (например, когда база в режиме Предприятия работает нормально, а войти невозможно только в Конфигуратор, или наоборот, или проблема возникает только под определёнными пользователями) рассматривать не буду, т.к. в Интернете есть масса советов по решению подобных проблем — от очистки кэша и «перезаливки» конфигурации, до обновления версии платформы и выгрузки всех данных в чистую базу. Буду рассматривать самые сложные случаи, когда в базу невозможно зайти ни в режиме Предприятия, ни в режиме Конфигуратора ни под одним из пользователей. Симптомы при этом могут быть разные: 1С «зависает» при попытке войти в базу, либо выдаёт сообщения типа «Ошибка формата потока», «База данных полностью разрушена», «Файл базы данных поврежден», «При обновлении данных, после последней реструктуризации, произошла критическая ошибка», «Обнаружена незавершенная операция сохранения конфигурации», либо «падает» с сообщением об ошибке приложения от операционной системы.
image1.png

Первоначальные действия для диагностирования таких случаев должны быть такими:

1. Обязательно делаем самый первоначальный бэкап нашей проблемной базы (до любых манипуляций с ней) копированием/архивированием файла 1Cv8.1CD, и убираем его в надёжное место, дабы случайно не повредить.
2. Пробуем войти в базу под другими пользователями.
3. Полностью очищаем кэш 1С (это можно сделать, например, простым удалением базы из списка, и добавлением её в список вновь, либо использовать утилиты типа http://infostart.ru/public/90572/ , либо удалить вручную http://help1c.com/faq/view/1267.html ).
4. Пробуем перенести файл базы на другой компьютер, и войти в базу там.
5. Прибегаем к помощи утилиты chdbfl.exe из поставки 1С:Предприятие, с установленной галкой «Исправлять обнаруженные ошибки».
6. Ещё можно попробовать открыть базу на более свежих релизах 1С, например, если работали на 8.2.15, то можно попробовать на 8.2.17.
image2.png

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

Итак, Вы решили починить базу своими руками, и окунуться в самые дебри загадочного содержимого файла 1Cv8.1CD. Какие же полезные статьи и инструменты мы имеем на текущий день?

1. Перво-наперво советую ознакомиться со статьями уважаемого awa http://infostart.ru/public/19734/ и http://infostart.ru/public/187832/ , содержащими описание формата файловой базы данных .1CD. Крайне настоятельно рекомендую прочитать, осмыслить, и отложить в памяти. Ведь без ясного представления устройства базы заниматься её ремонтом весьма проблематично.
2. Ещё есть официальная информация о предназначении некоторых таблиц БД от 1С: http://1c-dn.com/library/data_structure_in_1c_enterprise_8/?SECTION_CODE=data_structure_in_1c_enterprise_8&print=Y (к сожалению, только анголязычная).
3. Неофициальная информация о таблицах и полях: http://main.1c-ei.ru/Home/help/objectdb/dbschema (русскоязычная и более развёрнутая)
4. Далее, есть прекрасная утилита Tool_1CD http://infostart.ru/public/19633/ , позволяющая визуально просмотреть и извлечь данные из файла .1CD в xml-файлы, а также сохранить конфигурацию БД, основную конфигурацию и конфигурацию поставщика. Если из рухнувшей базы нужно спасти только конфигурацию — то самым лёгким и простым вариантом является именно она. Выгруженные в xml-файлы данные частично можно подгрузить в другую базу при помощи разработки http://infostart.ru/public/143704/ , однако поддерживается только определённый перечень объектов.
5. Система восстановления баз 1С restoration-base-1c8: http://code.google.com/p/restoration-base-1c8/downloads/list . Является конфигурацией для 1С, позволяющей загрузить и редактировать в ручном режиме содержимое файловой базы. Загрузка базы происходит очень долго, следует запастить терпением. Считывает блоки, не опираясь на данные корневого объекта, поэтому, если имеем базу с полностью разрушенным корневым объектом, то может быть весьма полезна. Описание примера применения: http://infostart.ru/public/158034/
6. Компонента 1CDLib для прямого чтения/записи данных из файлов баз данных .1CD http://infostart.ru/public/166557/ Компонента для прямого чтения/записи данных из файлов баз данных .1CD — инструмент, позволяющий не только читать данные из файловой базы, но и записывать. Данная компонента позволяет применять к файловым базам многие имеющиеся на просторах Интернета советы по ремонту клиент-серверных баз (MS SQL, PostgreSQL и т.д.), например: http://www.gilev.ru/1c/81/restore/ , http://infostart.ru/public/116123/ . Поскольку является внешней компонентой для 1С, позволяет в 90% случаев ремонтировать базы при помощи написания определённого кода (скрипта) на языке 1С после проведения процедуры обследования, не прибегая к hex-редактору.
7. Hex-редактор HxD http://mh-nexus.de/en/hxd/ (на случай, если что-то надо посмотреть или подправить непосредственно и в ручном режиме). В принципе, можно использовать любой, но мне понравился этот.
image3.png

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

Этап 1. Обследование, определение проблемных мест.

Итак, перед нами «мёртвая» файловая база. Задача, которая стоит перед нами на текущий момент — всесторонне обследовать базу, составить максимально полный перечень проблемных мест (ошибок). Одной из распространённых ошибок у начинающих специалистов является следующая: они либо сразу и надолго «ныряют» в содержимое файла базы в hex-редакторе, пытаясь вручную разобраться в тоннах байт, что, естественно, через некоторое время вызывает эффект отторжения, либо, попробовав один какой-нибудь инструмент, и получив неудачу, выдают заключение: «База не подлежит ремонту». Лично я считаю, что к услугам hex-редактора нужно прибегать только в исключительных случаях, либо изредка, на минутку, например, чтобы своими глазами посмотреть содержимое, находящееся по определённому смещению.
А перечень инструментов и приёмов для получения информации о проблемных местах вообще довольно широк, причём даже сама платформа 1С предоставляет, как минимум, два штатных способа. Рассмотрим их поподробнее.

1. Утилита chdbfl.exe из поставки 1С:Предприятие. Запускаем её с установленной галкой «Исправлять обнаруженные ошибки».
image5.png
Сразу хочу оговориться, что на данном этапе эта утилита будет использоваться нами исключительно для диагностики, поэтому, даже если она и выдаст нам какой-то изменённый, якобы отремонтированный файл базы, мы не имеем на него каких-то видов, и просто «выкидываем». Однако, внимательно изучаем протокол работы и фиксируем перечень ошибок, найденных этой утилитой.
Например, «Поврежден заголовок файла базы данных» чаще всего означает просто некорректно записанную в нём длину файла в блоках, а не полное его разрушение (чтобы в этом убедиться, достаточно на пару секунд обратиться к hex-просмотрщику или редактору, если в начале файла сигнатура 1CDBMSV8 на месте, значит, проблема только в поле длины). «Повреждено содержимое внутреннего файла » означает, что в корневом объекте существуют «битые записи», с некорректными номерами блоков заголовков, либо с испорченными блоками заголовков. И так далее.

2. Технологический журнал (ТЖ) 1С:Предприятие. Прекрасная возможность узнать, на каком месте «спотыкается» платформа, если она «зависает», «падает», или выдаёт загадочное сообщение «Ошибка формата потока» (причём сама ошибка может быть где угодно, в любом из файлов системных таблиц). Закрываем все сеансы 1С, чтобы они нам не мешались, и настраиваем запись ТЖ. Для этого идём в папку «bin», где лежат исполняемые файлы текущей плафтормы «1cv8*.exe», находим там вложенную папку «conf», и создаём там файл настройки записи ТЖ «logcfg.xml» примерно следующего содержания (исходный текст файла настройки есть в прикреплённом архиве):
image4.png

Вместо «C:1cv8logs» можно указать любую существующую папку, куда будут писаться логи, но лучше создать новую, пустую, чтобы не было проблем с записью логов.
(Подробнее про настройку ТЖ можно почитать, например, здесь: http://help1c.com/faq/view/464.html )
Далее, запускаем нашу проблемную базу в режиме конфигуратора, дожидаемся вывода окошка с ошибкой, или краха приложения, и сразу же идём изучать содержимое записанного лога (он будет в файле «1cv8_PIDМеткаДаты.log»). На следующие события и ошибки не обращаем внимания (их наличие является нормальным):

Exception=NetDataExchangeException,Descr='server_addr=any:port_num descr=Ошибка сетевого доступа к серверу...
Exception=DatabaseException8,Descr="Отсутствует файл базы данных 'ПутьКБазе/1Cv8tmp.1CD'"
Файл не обнаружен 'SprScndInfo'

и некоторые другие.
Собственно, мы даже можем не увидеть там нужного нам сообщения об ошибке, но зато мы увидим, при работе с каким объектом (таблицей или внутренним файлом таблицы) происходит ошибка.
image1.png

1С:Предприятие начинает загрузку базы с чтения содержимого системных таблиц. Системными таблицами являются:
V8USERS — таблица с данными пользователей (для баз версий 8.2 и выше)
DBSCHEMA — схема (структура) БД
_USERSWORKHISTORY — история работы пользователей
_COMMONSETTINGS, _FRMDTSETTINGS, _REPSETTINGS, _REPVARSETTINGS, _SYSTEMSETTINGS — хранилища различных настроек
а также системные таблицы-каталоги:
PARAMS — содержит файлы с параметрами БД
FILES — содержит прочие системные (служебные) файлы
CONFIG — содержит файлы конфигурации БД. Здесь же, в файлах с названиями вида GUID.GUID хранятся конфигурации поставщика (отсутствие таковых является нормальной ситуацией, означающей, что либо конфигурация полностью совпадает с типовой (не включен режим изменения), либо она снята с поддержки, либо является самописной).
CONFIGSAVE — содержит файлы основной конфигурации. Отсутствие записей в ней является нормальной ситуацией, означающей, что основная конфигурация полностью совпадает с конфигурацией БД. Стоит отметить, что здесь могут содержаться не все файлы конфигурации, а только изменённые (отличающиеся от файлов конфигурации БД).
Системные таблицы-каталоги являются, по сути, аналогами каталога в обычной файловой системе, т.е. являются хранилищем некоторого набора файлов, и имеют следующие поля:
FILENAME — имя файла
CREATION/MODIFIED — дата создания/изменения
ATTRIBUTES — атрибуты
DATASIZE — размер файла
BINARYDATA — содержимое файла (двоичные данные)

В случае полного отсутствия какой-либо системной таблицы (не путать с наличием пустой таблицы) 1С при старте базы выдаст сообщение «База данных полностью разрушена».

Теперь мы понимаем, что записи в ТЖ типа

22:42.0169-1,DBV8DBEng,2,process=1cv8,Trans=0,Func=selectFileName,FileName=ibparams.inf
22:42.0170-3,DBV8DBEng,1,process=1cv8,Trans=0,Func=readFile,CatName=Params,FileName=ibparams.inf

означают чтение файла «ibparams.inf» из таблицы PARAMS.

Итак, анализируем файл лога. Например, если происходит «Ошибка формата потока», а в конце файла лога мы видим примерно следующее:

41:29.3460-1,DBV8DBEng,2,process=1cv8,Usr=Админ,Trans=0,Func=restoreObject,tableName=DBChanges
41:29.3900-439,DBV8DBEng,2,process=1cv8,Usr=Админ,Trans=0,Func=restoreObject,tableName=DBSchema
41:29.3901-443,SDBL,1,process=1cv8,Usr=Админ,Trans=0,Sdbl=GET NGENERATIONS
41:29.4060-19207,SESN,1,process=1cv8,Func=Attach,IB=ПутьКБазе,Nmb=2,ID=GUID
41:29.4061-19210,SESN,1,process=1cv8,Func=Finish,IB=ПутьКБазе,Nmb=2,ID=GUID

то можно заключить, что ошибка формата потока возникла при работе с содержимым таблицы «DBSchema», следовательно, содержимое этой таблицы нужно будет изучить поподробнее.
Ещё, если в наличии есть какой-нибудь старый бэкап, можно применить такой приём: записать ТЖ при его старте, и сравнить его с ТЖ при старте проблемной базы, чтобы понять, какими сообщениями об исключениях можно пренебречь, а также, какие этапы при старте проблемной базы проходят нормально, а до каких дело не доходит.
По окончании данной процедуры файл «logcfg.xml» можно переименовать, чтобы не засорять ненужными логами диск.

3. Открываем нашу базу при помощи утилиты Tool_1CD. Здесь мы можем просмотреть таблицы, а также их содержимое (данные записей), причём для системных таблиц (DBSCHEMA, PARAMS и т.д.) поддерживается автоматическая распаковка содержимого BLOB-полей, вплоть до показа содержимого упакованных контейнеров (в таблицах CONFIG и CONFIGSAVE). Наиболее пристальное внимание уделяем тем проблемным объектам, которые были нами найдены по результатам действий из пунктов 1 и 2, а также системным таблицам (хотя, зачастую список проблемных объектов, составленный по п. 1 и 2, ограничивается именно системными таблицами).
image2.png
При просмотре перечня таблиц смотрим, есть ли таблицы с окончаниями «OG» — их наличие означает, что крах базы произошёл при ТиИ или реструктуризации (в процессе выполнения этих операций 1С создаёт новые таблицы с такими окончаниями, куда пишутся данные реструктуризованных таблиц, затем исходная таблица удаляется, а новой назначается исходное имя). Также бывает полезно сравнить перечень таблиц с содержимым старого бэкапа (при его наличии, и при условии, что конфигурация не обновлялась, иначе состав таблиц, связанных с метаданными, конечно, будет различаться), это поможет выявить отсутствующие таблицы.
При просмотре таблицы CONFIG обращаем внимание, есть ли в ней файлы с окончаниями «.new» — их наличие означает, что крах базы произошёл при обновлении конфигурации БД.
Также утилита позволяет сохранить конфигурацию БД в cf-файл, что и рекомендуется сделать. Загружаем далее эту конфигурацию из файла в пустую базу, и пробуем запустить. Если всё запустилось успешно, значит, проблема нашей базы не в конфигурации.

4. Открываем базу при помощи компоненты 1CDLib. Информация из п. 3 в полной мере относится и к этому пункту, меняется только методика работы с файлом базы — посредством скриптов, использующих функции компоненты, с последующим анализом лог-файла и извлечённых данных.
Вашему вниманию представлены два скрипта (являющихся внешними обработками для режима управляемого приложения 1С:Предприятие 8.2, их можно запустить, например, из созданной пустой базы), с помощью которых можно произвести полуавтоматическое обследование проблемной базы:
Обработка «SaveAllTables.epf» позволяет сохранить данные всех таблиц в виде структуры вложенных папок и файлов в папке «Objects» (создаётся там же, где находится файл базы), и далее их можно изучать при помощи обычного файлового менеджера. Также, после сохранения всех таблиц, полезно изучить содержимое лога «logdb1cd.log» — туда выводятся сообщения об ошибках, которые произошли при извлечении таблиц. Если сообщения об ошибках в нём отсутствуют, то можно сказать, что физических ошибок в структуре хранения таблиц в файле базы нет, и проблемы уже либо в отсутствии каких-то таблиц, либо в их некорректном содержимом.
Обработка «ViewRecords.epf» позволяет просматривать записи таблиц и сохранять в файлы BLOB-данные (файлы создаются в папках с именами соответствующих таблиц), предназначена, в первую очередь, для полуавтоматического анализа содержимого системных таблиц (хотя с помощью неё можно просмотреть и другие таблицы). В случае ошибок при извлечении BLOB-данных, или при их распаковке (если содержимым BLOB-поля являются запакованные по алгоритму Deflate данные), выводятся соответствующие сообщения.
image3.png

5. Загрузка базы в систему восстановления баз 1С restoration-base-1c8. По состоянию дел на текущий момент, в данном продукте многие функции не реализованы, а некоторые, на мой взгляд, реализованы не совсем прозрачно. Кроме того, практически вся смысловая обработка данных происходит на стороне 1С, что далеко не лучшим образом сказывается на быстродействии. Например, у меня полная загрузка файла размером 230 Мб длилась около часа, за это время я уже всесторонне обследовал базу другими инструментами, и приступил к непосредственному ремонту. Окончания же загрузки файла размером 1,5 Гб я вообще не дождался — закончилось терпение. Ещё один нюанс: поскольку система является конфигурацией для 1С, то все данные исходной базы загружаются также в базу 1С, но оказываются они в табличной части одного справочника. Следовательно, даже не принимая во внимание скорость загрузки, в случае файловой базы не получится загрузить файл с исходной базой размером более 4 Гб (из-за ограничений формата). Тем не менее, проект является свободным, с открытым кодом, доступным для изменения и доработки, поэтому не могу не упомянуть про него.

Загрузив нашу базу в систему restoration-base-1c8, мы можем исследовать список таблиц:
image6.png
а также просмотреть и отредактировать данные любого блока во встроенном hex-редакторе:
image7.png
Просмотр записей таблиц, к сожалению, не реализован.

На этом наш список, а также сам этап обследования заканчивается. Аккуратно фиксируем и систематизируем всю собранную информацию, которую мы будем использовать далее, в процессе «лечения». Конкретные, наиболее типичные проблемные ситуации и способы их устранения будут рассмотрены в следующих разделах.

Файлы:
Обработки с поддержкой формата БД 8.3.8:
Обработки для обследования.zip

Этап 2. Лечим базу.

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

В общем виде, скрипт выглядит так:

    FileDB=Новый("AddIn.T1CDLib.DB1CD");
    FileDB.OpenLogFile(ИмяЛога);
    Состояние("Чтение структуры файла");
    FileDB.Open1CDFile(ИмяФайла);
    Состояние("Обработка файла");

    // здесь выполняем различные операции по лечению базы

    FileDB.CloseFile();
    FileDB.CloseLogFile();

    Состояние("");

В зависимости от списка проблем, составленного на этапе обследования, можно выполнить различные операции:
1. Если в заголовке базы указан неверный размер, то исправляем заголовок:

    FileDB.FixMainStreamHeader();

2. Если есть таблицы с некорректным размером одного или нескольких объектов (описание, записи, BLOB, индексы):

    FileDB.FixTableHeaders("TABNAME",Истина,Истина,Истина,Истина);

В моей практике бывали случаи, что chdbfl.exe при некорректном размере объектов какой-то таблицы не мог восстановить добрую половину данных этой таблицы, а вот после исправления размеров «терял» буквально пару-тройку записей, и это безо всякого изменения содержимого объектов такой таблицы.
3. Если есть некорректные записи в корневом объекте RootEntry:
Вывести содержимое корневого объекта в лог-файл можно так:

    FileDB.PrintRootEntry();

Удалить некорректную запись по индексу (нумерация — с 1) из корневого объекта:

FileDB.DeleteTableFromRootEntry(ИндексЗаписи);

Если содержимое какой-то потерянной таблицы нашлось в недрах файла БД (например, при помощи поиска в Hex-редакторе), но ссылка на неё отсутствует в корневом объекте, можно её добавить:

    FileDB.AddTableToRootEntry(ИндексБлокаЗаголовкаОписанияТаблицы);

Внимание: после манипуляций с корневым объектом нужно переоткрыть БД:

    FileDB.CloseFile();
    FileDB.Open1CDFile(ИмяФайла);

4. Если в перечне таблиц базы есть таблицы с окончаниями «OG», это означает, что база рухнула в процессе реструктуризации или ТиИ. В данном случае может помочь такая операция (удаление окончания из имени таблиц):

    ArrayPres=FileDB.GetTablesArray(Ложь);
    TablesArray=РазвернутьЗначение(ArrayPres);

    Для TabInd=1 По TablesArray.Count() Цикл
        TableInfo=TablesArray[TabInd-1];
        TableName=TableInfo.Name;
        Если ВРег(Прав(TableName,2))="OG" Тогда
            МасПереимТаб.Добавить(TableName);
        КонецЕсли;

    КонецЦикла;

    Состояние("Переименование таблиц");

    Для каждого ТекТаб из МасПереимТаб Цикл
        FileDB.RenameTable(ТекТаб,Лев(ТекТаб,СтрДлина(ТекТаб)-2));
    КонецЦикла;

Однако, надо понимать, что содержимое таких таблиц может не соответствовать текущей конфигурации БД. В случае ТиИ вероятность несоответствия невысока, а вот при прерванном обновлении может быть по-разному, но, в любом случае, попробовать стоит.

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

    МасПереносТаб=Новый Массив;
    МасПереносТаб.Добавить("Reference19");
    МасПереносТаб.Добавить("Document192");

    ПапкаБазы="ПутьКПроблемнойБазе";
    ПапкаБазыПред="ПутьКБазеИзБэкапа";
    ИмяФайла=ПапкаБазы+"1Cv8.1CD";
    ИмяФайлаПред=ПапкаБазыПред+"1Cv8.1CD";

    FileDB=Новый("AddIn.T1CDLib.DB1CD");
    Состояние("Чтение структуры файла");
    FileDB.Open1CDFile(ИмяФайла);

    FileDB2=Новый("AddIn.T1CDLib.DB1CD2");
    FileDB2.Open1CDFile(ИмяФайлаПред);

    Состояние("Перенос таблиц");

    Для каждого ТекТаб из МасПереносТаб Цикл
        TableName=ТекТаб;
        ПапкаТаб=ПапкаБазыПред+TableName+"";
        ВремКат=Новый Файл(ПапкаТаб);
        Если (НЕ ВремКат.Существует()) Тогда
            СоздатьКаталог(ПапкаТаб);
        КонецЕсли;

        FileNameDescription=ПапкаТаб+"Description";
        FileNameRecords=ПапкаТаб+"Records";
        FileNameBLOB=ПапкаТаб+"BLOB";
        FileNameIndexes=ПапкаТаб+"Indexes";

        FileDB2.SaveTableDataToFile(TableName,FileNameDescription,FileNameRecords,FileNameBLOB,FileNameIndexes);

        FileDB.LoadTableDataFromFile(TableName,FileNameDescription,FileNameRecords,FileNameBLOB,FileNameIndexes);
    КонецЦикла;

    FileDB.CloseFile();

    FileDB2.CloseFile();

Естественно, ссылки на элементы этих таблиц, созданные после бэкапа, будут «битыми», однако это всё же лучше, чем ничего.

Нумерация пунктов соответствует рекомендуемому порядку операций: т.е., сначала нужно исправить заголовки базы и таблиц, затем «разобраться» с корневым объектом, а затем уже приступать к манипуляциям с таблицами.

Также нужно помнить, что после всех проделанных манипуляций очеь полезно «шлифануть» базу утилитой chdbfl.exe с установленной галкой «Исправлять обнаруженные ошибки». Эта процедура перепакует данные всех таблиц, избавив их от мусора и удалённых записей, а также полностью перестроит индексы (а из-за «протухших» индексов база может по-прежнему не запускаться ни в одном из режимов, хотя сами данные могут быть уже восстановлены полностью).

В следующем разделе будут рассмотрены различные ситуации при наличии проблем в конфигурации (таблицах CONFIG и CONFIGSAVE).

Этап 3. Лечим конфигурацию.

Проблемы в таблицах конфигурации — одна из самых частых причин «падения» файловой БД. Последствия бывают как лёгкие (невозможность открытия определённых объектов в режиме Предприятия и/или Конфигуратора, обновления конфигурации), так и тяжёлые (невозможность открытия БД ни в режиме Предприятия, ни в режиме Конфигуратора).

Как мы помним, конфигурация хранится в двух таблицах: CONFIG — содержит файлы конфигурации БД, CONFIGSAVE — содержит файлы основной (сохранённой, редактируемой) конфигурации. Если на этапе обследования были выявлены проблемы в этих таблицах («битые» записи/файлы, существенно меньшее количество файлов по сравнению с типовой конфигурацией или конфигурацией из последнего бэкапа (это не касается таблицы CONFIGSAVE, т.к. для неё уменьшение количества записей может являться нормальной ситуацией, означающей, что изменения из основной конфигурации перенесли в конфигурацию БД), наличие файлов с окончаниями «.new» в имени, и пр.), то пора приступать к их лечению (для этого прибегнем к помощи компоненты 1CDLib).

Начнём с лёгкого — таблицы CONFIGSAVE. Поскольку утеря содержимого этой таблицы не очень страшна (будут лишь утеряны сохранённые, но не перенесённые в БД изменения конфигурации), то самым кардинальным способом является полная очистка содержимого данной таблицы:

    FileDB=Новый("AddIn.T1CDLib.DB1CD");
    Состояние("Чтение структуры файла");
    FileDB.Open1CDFile(ИмяФайла);

    FileDB.OpenTable(0,"CONFIGSAVE");
    FieldFileName="FILENAME";

    Состояние("Перебор записей");
    Рез=FileDB.MoveFirstRecord(0);
    Пока Рез Цикл
        Если НЕ FileDB.IsRecordDeleted(0) Тогда
            FileDB.DeleteRecord(0);
        КонецЕсли;

        Рез=FileDB.MoveNextRecord(0);
    КонецЦикла;

    FileDB.CloseFile();

В результате основная конфигурация будет приведена к конфигурации БД.

Также можно попытаться перенести данные этой таблицы из последнего бэкапа, но только в том случае, если с момента бэкапа изменения не переносились в конфигурацию БД. Хочется отметить, что вероятность наличия такого бэкапа ничтожно мала, но, всё-таки, отметим эту возможность.

Теперь перейдём к таблице CONFIG. Если содержимое этой таблицы сильно повреждено, пути восстановления следующие:
1.Если есть бэкап, с момента которого изменения в конфигурацию БД не вносились, или вносились незначительные изменения, не повлёкшие за собой реструктуризацию БД, то самый простой путь — перенести данные этой таблицы из бэкапа:

    МасПереносТаб=Новый Массив;
    МасПереносТаб.Добавить("CONFIG");

    ПапкаБазы="ПутьКПроблемнойБазе";
    ПапкаБазыПред="ПутьКБазеИзБэкапа";
    ИмяФайла=ПапкаБазы+"1Cv8.1CD";
    ИмяФайлаПред=ПапкаБазыПред+"1Cv8.1CD";

    FileDB=Новый("AddIn.T1CDLib.DB1CD");
    Состояние("Чтение структуры файла");
    FileDB.Open1CDFile(ИмяФайла);

    FileDB2=Новый("AddIn.T1CDLib.DB1CD2");
    FileDB2.Open1CDFile(ИмяФайлаПред);

    Состояние("Перенос таблиц");

    Для каждого ТекТаб из МасПереносТаб Цикл
        TableName=ТекТаб;
        ПапкаТаб=ПапкаБазыПред+TableName+"";
        ВремКат=Новый Файл(ПапкаТаб);
        Если (НЕ ВремКат.Существует()) Тогда
            СоздатьКаталог(ПапкаТаб);
        КонецЕсли;

        FileNameDescription=ПапкаТаб+"Description";
        FileNameRecords=ПапкаТаб+"Records";
        FileNameBLOB=ПапкаТаб+"BLOB";
        FileNameIndexes=ПапкаТаб+"Indexes";

        FileDB2.SaveTableDataToFile(TableName,FileNameDescription,FileNameRecords,FileNameBLOB,FileNameIndexes);

        FileDB.LoadTableDataFromFile(TableName,FileNameDescription,FileNameRecords,FileNameBLOB,FileNameIndexes);
    КонецЦикла;

    FileDB.CloseFile();

    FileDB2.CloseFile();

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

2. Если конфигурация является полностью типовой, либо типовой с незначительными изменениями, не повлёкшими за собой реструктуризацию БД, и которыми можно пренебречь, то можно перенести конфигурацию из развёрнутой новой базы с типовой конфигурацией. Но здесь есть одна проблемка — как точно узнать нужный релиз, если база не открывается ни в одном режиме? Выход есть: открываем декомпрессированное содержимое файла «root» — там мы увидим GUID нужного нам файла (например, для БП 2.0 это «e0666db2-45d6-49b4-a200-061c6ba7d569»), далее открываем декомпрессированное содержимое этого файла — там, недалеко от начала файла, мы увидим название конфигурации, редакцию, название и копирайты разработчика, и, что самое важное, номер релиза.
Скрин1.png
Далее — дело техники, нужно найти нужный релиз типовой конфигурции и перенести содержимое таблицы CONFIG в нашу проблемную базу. (Извлечь содержимое таблицы CONFIG можно при помощи обработки ViewRecords.epf из 1. Обследование.)

3.Если база рухнула во время обновления конфигурации БД (характерным признаком этого является наличие файлов с окончаниями «.new» в имени), то может помочь вот такой скрипт (удаляет файлы с окончаниями «.new»):

    FileDB=Новый("AddIn.T1CDLib.DB1CD");
    Состояние("Чтение структуры файла");
    FileDB.Open1CDFile(ИмяФайла);

    FileDB.OpenTable(0,"CONFIG");
    FieldFileName="FILENAME";

    Состояние("Перебор записей");
    Рез=FileDB.MoveFirstRecord(0);
    Пока Рез Цикл
        Если НЕ FileDB.IsRecordDeleted(0) Тогда
            FileName=FileDB.ReadSimpleValue(0,FieldFileName);
            Если (Прав(FileName,4)=".new") Тогда
                FileDB.DeleteRecord(0);
            КонецЕсли;
        КонецЕсли;

        Рез=FileDB.MoveNextRecord(0);
    КонецЦикла;

    FileDB.CloseFile();

В данной статье приведены наиболее типичные скрипты. Путей восстановления конфигурации, конечно, намного больше, можно написать любой скрипт с использованием функций компоненты 1CDLib — переименование, удаление файлов по определённым условиям, перенос определённых файлов из другой базы, и т.д.
Например, рецепты восстановления клиент-серверных БД типа http://infostart.ru/public/138797/ (приведён рецепт лечения после неудачного динамического обновления) легко и непринуждённо можно применять и для файловых баз, причём безо всяких лазаний в дебрях файла БД с Hex-редакторами и прочими «напильниками».
Сравните, например, шаманские танцы с бубном в http://infostart.ru/public/154556/ , которые ещё и не всегда могут увенчаться успехом, и простенький скрипт

    FileDB.OpenTable(0,"CONFIG");
    FieldFileName="FILENAME";

    Состояние("Перебор записей");
    Рез=FileDB.MoveFirstRecord(0);
    Пока Рез Цикл
        Если НЕ FileDB.IsRecordDeleted(0) Тогда
            FileName=FileDB.ReadSimpleValue(0,FieldFileName);
            Если (FileName="сommit") ИЛИ (FileName="dbStruFinal") Тогда
                FileDB.DeleteRecord(0);
            КонецЕсли;
        КонецЕсли;

        Рез=FileDB.MoveNextRecord(0);
    КонецЦикла;


Надеюсь, что данная статья поможет Вам в восстановлении базы, но ещё лучше не забывать про ежедневные бэкапы.

После того, как я выложил свою программку Tool_1CD ( http://infostart.ru/projects/3851/ ), оказалось, что интерес к формату файлов 1CD достаточно велик. Поэтому для всех желающих продолжить разбираться с форматом, или желающих написать свою программу, выкладываю свои текущие знания об этом формате.

Описание формата приведено в терминах языка C. Размер типа char – 1 байт, размер типа short int – 2 байта, размер типа int и unsigned int – 4 байта. Префиксом 0x обозначаются шестнадцатеричные числа.

Файлы баз *.1CD состоят из блоков длиной 4096 байт (0x1000). Соответственно, длина файла всегда кратна 4096.

Блок 0

Нулевой блок имеет следующую структуру:

struct {

char sig[8]; // сигнатура “1CDBMSV8”

char ver1;

char ver2;

char ver3;

char ver4;

unsigned int length;

int unknown;

}

Первые 8 байт – сигнатура базы «1CDBMSV8».

Следующие 4 байта — это версия базы. На данный момент мне встречались только версия «8.0.5.0» (ver1 = 8, ver2 = 0, ver3 = 5, ver4 = 0) – это базы 1Cv8.0 и версия «8.1.0.0» (ver1 = 8, ver2 = 1, ver3 = 0, ver4 = 0) – это базы 1Cv8.1 и 1Cv8.2.

Следующие 4 байт – длина базы (файла) в блоках.

Предназначение поля unknown неизвестно, всегда содержит 1.

Объекты

Вся остальная информация в базе хранится в объектах (файлах базы). Каждый объект состоит из одного или более блоков. У каждого объекта есть один заголовочный блок, блоки с таблицей размещения, и собственно данные. Второе и третье может отсутствовать.

Структура первого блока каждого объекта такова:

struct {

char sig[8]; // сигнатура “1CDBOBV8”

int length; // длина содержимого объекта

int version1;

int version2;

unsigned int version;

unsigned int blocks[1018];

}

Первые 8 байт – сигнатура базы «1CDBOBV8».

Есть 2 типа объектов.

Блок 1. Таблица свободных блоков

Первый тип объекта – это таблица свободных блоков. Признаком этого блока является поле version равное 0. Такой объект в базе всегда один, и его заголовочный блок располагается всегда в блоке со смещением 1 (т.е. по адресу 0x1000). Длина данных такого объекта равна (length * 4) байт.

В blocks содержатся номера блоков, в которых собственно и находится содержимое таблицы свободных блоков. Значащими являются ненулевые значения в массиве blocks. Содержимое таблицы свободных блоков – это просто массив номеров свободных блоков:

unsigned int free_blocks[length];

Таким образом, в базе содержатся ровно length свободных блоков.

Когда системе требуется новый блок для данных, то она берет последний свободный блок из массива free_blocks и уменьшает length на 1. Если свободных блоков нет, то он создается в конце файла базы. Блоки, содержащиеся в массиве blocks, не являются свободными, а принадлежат объекту – таблице свободных блоков. В blocks может содержаться больше блоков, чем необходимо для хранения массива free_blocks.

Остальные объекты

Второй тип объектов характеризуется ненулевым значением поля version. Вся информация в базе, кроме блока 0 и таблицы свободных блоков хранится именно в таких объектах.

В поле length содержится длина в байтах данных объекта.

В массиве blocks находятся индексы блоков, содержащих таблицу размещения данных объекта. Каждый блок, указанный в blocks, и являющийся частью таблицы размещения, имеет следующую структуру:

struct {

int numblocks;

unsigned int datablocks[1023];

}

Поле numblocks указывает количество реальных значений в datablocks (от 1 до 1023). В datablocks содержатся индексы блоков, в которых находится собственно содержимое объекта (данные). Так как в одном блоке таблицы размещения может быть указано максимум 1023 блока с данными, то соответственно, максимальная длина данных, указанных в одном блоке таблицы размещения равна 1023 * 4096 = 4190208 байт (0x3ff * 0x1000 = 0x3ff000). Таким образом, из длины содержимого объекта length мы можем определить количество фактических значений в blocks. Если length равен 0, то в blocks нет значащих данных, иначе количество значений в blocks равно (length — 1) / 0x3ff000 + 1 (деление целочисленное, без остатка). А также можно вычислить максимальную длину данных одного объекта: 4190208 * 1018 = 4265631744 байт (1018 – максимальное количество значений в массиве blocks), это совсем немного меньше 4х гигабайт.

Повторим, в заголовочном блоке объекта находится массив blocks, содержащий индексы блоков с таблицей размещения. А в таблице размещения находятся блоки, содержащие сами данные.

Блок 2. Корневой объект

Последним объектом с предопределенным расположением является корневой объект. Заголовочный блок корневого объекта располагается в блоке с индексом 2. Все остальные объекты базы могут быть получены через корневой объект. Структура данных этого объекта зависит от версии базы, хотя и различается несильно. Для версии базы «8.0.5.0» эта структура выглядит так:

struct {

char lang[8];

int numblocks;

int tableblocks[numblocks];

}

Для версии «8.1.0.0» структура выглядит так:

struct {

char lang[32];

int numblocks;

int tableblocks[numblocks];

}

Т.е. различаются эти структуры только длиной поля lang. В поле lang содержится код языка базы. Код языка базы представляет собой строку в ANSI-кодировке. Мне встречались только базы с кодами «ru_RU» и «en». На что влияют эти коды языка, я не знаю, возможно, на порядок сортировки строк при построении индексов.

В поле numblocks содержится количество элементов в массиве tableblocks. В массиве же tableblocks содержатся индексы объектов, содержащих все таблицы данных. Т.е. таблиц в базе ровно numblocks.

Объект таблицы

Каждый объект таблицы, указанный в корневом объекте, содержит просто текстовое описание таблицы в Unicode. Вот пример описания таблицы:

{«_Reference4»,0,

{«Fields»,

{«_IDRREF»,»B»,0,16,0,»CS»},

{«_VERSION»,»RV»,0,0,0,»CS»},

{«_MARKED»,»L»,0,0,0,»CS»},

{«_ISMETADATA»,»L»,0,0,0,»CS»},

{«_CODE»,»NC»,0,9,0,»CI»},

{«_DESCRIPTION»,»NVC»,0,25,0,»CI»},

{«_FLD7″,»I»,1,0,0,»CS»}

},

{«Indexes»,

{«_IDRREFIDX»,1,

{«_IDRREF»,16}

},

{«_REFERENCE4_CODE_SR»,0,

{«_CODE»,9},

{«_IDRREF»,16}

},

{«_REFERENCE4_DESCR_SR»,0,

{«_DESCRIPTION»,25},

{«_IDRREF»,16}

}

},

{«Recordlock»,»0″},

{«Files»,118,119,96}

}

Как видно из этого примера, здесь присутствуют имя таблицы (_Reference4), раздел описания полей таблицы (Fields), раздел описания индексов (Indexes), параметр Recordlock и раздел Files.

В разделе Files всегда содержатся три числа, которые содержат индексы заголовочных блоков объектов (по порядку) с записями таблицы, Blob-данными (строки неограниченной длины и двоичные данные) и индексами. Если какого-либо объекта у таблицы нет, то соответствующее число равно нулю.

В разделе Fields содержатся описания полей таблицы. Описание каждого поля содержит (по порядку): имя поля (FieldName), тип поля (FieldType), признак использования NULL (NullExists), длину (FieldLength), точность (FieldPrecision) и признак регистрочувствительности (FieldCaseSensitive).

Сколько байт занимает каждое поле в записи, и как его интерпретировать, зависит от параметров поля. Во-первых, если NullExists у поля равен 1, то первый байт поля является признаком NULL. Значение 0 этого байта означает, что поле не содержит значение (т.е. содержит NULL). В противном случае, поле содержит значение. Если же NullExists равен 0, то такого байта в поле нет.

Далее, размер и формат поля зависит от типа поля. Типы поля бывают такими:

  • «B» — двоичные данные. Длина поля равна FieldLength байт.
  • «L» — булево. Длина поля 1 байт. Нулевое значение байта означает Ложь, иначе Истина.
  • «N» — число. Длина поля в байтах равна Цел((FieldLength + 2) / 2). Числа хранятся в двоично-десятичном виде. Первый полубайт означает знак числа. 0 – число отрицательное, 1 – положительное. Каждый следующий полубайт соответствует одной десятичной цифре. Всего цифр FieldLength. Десятичная точка находится в FieldPrecision цифрах справа. Например, FieldLength = 5, FieldPrecision = 3. Байты 0x18, 0x47, 0x23 означают число 84.723, а байты 0x00, 0x00, 0x91 представляют число -0.091.
  • «NC» — строка фиксированной длины. Длина поля равна FieldLength * 2 байт. Представляет собой строку в формате Unicode (каждый символ занимает 2 байта).
  • «NVC» — строка переменной длины. Длина поля равна FieldLength * 2 + 2 байт. Первые 2 байта содержат длину строки (максимум FieldLength). Оставшиеся байты представляет собой строку в формате Unicode (каждый символ занимает 2 байта).
  • «RV» — версия. Длина поля 16 байт. Предположительно содержит четыре числа int.
  • «NT» — строка неограниченной длины. Длина поля 8 байт. Первые четыре байта содержат начальный индекс блока в объекте Blob таблицы, вторые четыре – длину данных в объекте Blob. В объекте Blob содержится строка в формате Unicode.
  • «I» — двоичные данные неограниченной длины. Длина поля 8 байт. Первые четыре байта содержат начальный индекс блока в объекте Blob таблицы, вторые четыре – длину данных в объекте Blob.
  • «DT» — дата-время. Длина поля 7 байт. Содержит данные в двоично-десятичном виде. Первые 2 байта содержат четыре цифры года, третий байт – две цифры месяца, четвертый байт – день, пятый – часы, шестой – минуты и седьмой – секунды, все также по 2 цифры.

Зная теперь длину в байтах каждого поля можно посчитать общую длину одной записи таблицы и смещение каждого поля в записи. Но для этого необходимо учесть следующее. Если в описании полей таблицы нет поля с типом версия (RV), но при этом параметр Recordlock равен 1, то в записи присутствует дополнительное поле, которое я для себя называю короткая скрытая версия. Длина этого поля равна 8 байт. В каждой записи самый первый байт – это признак удаленности записи (признак, что запись не занята). Если этот байт равен 1, то запись свободна, а следующие 4 байта содержат индекс следующей свободной записи. Из этого следует, что запись не может быть короче пяти байт. Если же первый байт записи содержит 0, то далее в записи следуют значения полей. Причем порядок полей определяется таким образом: превым всегда идет поле версии (или описанное в разделе Fields с типом RV или поле скрытой короткой версии), затем все остальные поля в том порядке, как они описаны в разделе Fields.

Объект записей таблицы

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

Объект Blob таблицы

Объект содержит Blob-данные таблицы (строки неограниченной длины и двоичные данные неограниченной длины). Содержимое этого объекта состоит из блоков (не путать с блоками, из которых состоит файл 1CD) длиной 256 байт (0x100). Т.е. это просто массив блоков длиной 256 каждый. Поэтому длина данных объекта всегда кратна 256. Структура каждого блока объекта такова:

struct {

unsigned int nextblock;

short int length;

char[250] data;

}

Поле nextblock содержит индекс следующего блока, содержащего продолжение данных, или 0, если следующего блока нет. Поле length содержит длину данных в этом блоке (максимум 250). Поле data содержит сами данные. Нулевой блок всегда считается свободным, в поле nextblock он содержит индекс следующего свободного блока. Таким образом, с нулевого блока начинается цепочка свободных блоков.

В записях таблицы в полях с типом «NT» и «I» содержится индекс первого блока, с которого начинаются данные, относящиеся к этому полю данной записи.

Объект индексов таблицы

На данный момент структура индексов до конца не изучена.

Понравилась статья? Поделить с друзьями:
  • Как составить график дежурства на одного человека
  • После того как найдете сердца
  • Как найти среднегодовой темп роста в статистике
  • Как найти чистую зарплату
  • Как найти мусульманку для отношений