Продолжение. Предыдущие этапы:
Этап 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).