Продолжение. Предыдущие этапы:
Этап 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"), далее открываем декомпрессированное содержимое этого файла - там, недалеко от начала файла, мы увидим название конфигурации, редакцию, название и копирайты разработчика, и, что самое важное, номер релиза.
- Далее - дело техники, нужно найти нужный релиз типовой конфигурции и перенести содержимое таблицы 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 - переименование, удаление файлов по определённым условиям, перенос определённых файлов из другой базы, и т.д.
Например, рецепты восстановления клиент-серверных БД типа //infostart.ru/public/138797/ (приведён рецепт лечения после неудачного динамического обновления) легко и непринуждённо можно применять и для файловых баз, причём безо всяких лазаний в дебрях файла БД с Hex-редакторами и прочими "напильниками".
Сравните, например, шаманские танцы с бубном в //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);
КонецЦикла;
Надеюсь, что данная статья поможет Вам в восстановлении базы, но ещё лучше не забывать про ежедневные бэкапы.