Восстановление работоспособности файловой базы. 2. Лечение

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

Продолжение. Предыдущие этапы:

0. Введение

1. Обследование


Этап 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[TabInd1];
           
    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).

28 Comments

  1. DragonAgo

    Полезная статья, еще для серверных баз, только там больше ошибок, и все скорее всего просто не описать будет

    Reply
  2. TrinitronHome

    спасибо за данную статью, очень полезная информация для меня

    Reply
  3. soba

    Да, весьма подробно изложено. Спасибо, похоже пригодится совсем скоро.

    Reply
  4. teller

    (3) soba, похоже кого-то отговорил от резервного копирования и ТиИ ?

    Reply
  5. soba

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

    Reply
  6. wirg

    Интересно

    Reply
  7. denis1c@

    А можно ли вылечить файловую базу ЗУП, если утилита chdbfl.exe и ТиИ ни чего не находят, база запускается, работает нармально, но при групповом расчете НДФЛ база падает со словами «Недостаточно памяти»?

    Reply
  8. andrewks

    (7) denis1c@, а почему Вы решили, что база содержит физические ошибки?

    сколько сотрудников? какой релиз платформы и конфы?

    Reply
  9. yandextesting

    (7) недавно сталкивался с подобным вопросом, проблема оказалась в неверно заполненной дате документа по одному из сотрудников: вместо 2013 года был указан 0013 год н.э. 🙂 В результате ЗУП пыталась выполнить какие-то расчеты за пару тысяч лет… Вероятность того, что это проблема БД крайне мала, на мой взгляд — копайте данные.

    Reply
  10. mdie

    (7) denis1c@, запустите под отладчиком в режиме замера производительности и найдете момент «распутывая» от места проблемы. К тому же недавно также пришлось такое лечить, когда период регистрации/начисления у НДФЛ указали лет на 200 больше.

    А автору огромное спасибо за тулзу — реально помогла поднять базу с минимальными потерями.

    Reply
  11. s_uu

    А каков физический предел размера файловой базы данных?

    Reply
  12. andrewks

    (11) s_uu, теоретически его нет. есть ограничение на размер каждого из объектов таблицы (записи, блобы, индексы) — чуть менее 4 Гб. Самих таблиц может быть очень много.

    естественно, что на практике не всё так хорошо, но и не всё зависит от размера. если с базой активно работают более 5-ти человек одновременно, уже можно задумываться о серверной архитектуре, но есть и базы, прекрасно работающие и с 10-ю активными пользователями. так что всё индивидуально

    Reply
  13. denis1c@

    (9) Благодарю за наводку. Открыл регистр сведений «НДФЛ сведения о доходах» и увидел такую картину: Месяц налогового периода — февраль 0013 г. Оказывается в системе ввели документ начисление по б.л. этой датой.

    Спасибо всем за помощь. Проблема решена.

    Reply
  14. SeiOkami

    Круто было бы, если кто-нить сделает обработку для лечения базы всеми возможными способами =)

    Reply
  15. andrewks

    (14) SeiOkami, в данном вопросе универсализм не то, чтобы невозможен, а, скорее, вреден.

    на мой взгляд, правильный алгоритм именно такой — анализ и фиксация проблем, потом — написание/применение «лечебного» скрипта, исправляющего конкретные проблемы конкретной базы

    Reply
  16. SeiOkami

    (15) это, конечно, да. Однако, если сделать что-то вроде помощника диагностики проблем и по результатам задаваемых вопросов предлагать то или иное решение. Как в Windows… только рабочее =)

    Reply
  17. AVK_Alex

    Было бы удобно различные инструменты собрать под один GUI, да еще и с парсером логов… ну… и для полноты еще гравицапу добавить 🙂

    Reply
  18. shira84

    полезно

    Reply
  19. zels

    Диск при чтении дает ошибки CRC в районе 8-10Мб от начала файла 1CD (БП2.0). Если там находится конфигурация поставщика, то можно ее взять из старого архива и перенести в копию 1CD (где сбойные блоки забиты нулями)?

    Не стал разбираться — написал програмку, которая склеивает два 1CD-файла в один и все заработало.

    Вот ссылка: Склеивание двух 1CD-файлов в один

    Reply
  20. andrewks

    (19)

    Если там находится конфигурация поставщика, то можно ее взять из старого архива и перенести в копию 1CD (где сбойные блоки забиты нулями)?

    да, можно

    Reply
  21. sss999

    подскажите как удобнее искать частичные данные таблицы что бы восстановить, так как саму таблицу не находит ни какая программа, и как понять есть ли правильная запись по ней в парамс или сама таблица повреждена, если повреждено описание то как посмотреть целые ли данные?

    Reply
  22. KazanKokos

    (12) Под rdp в файловой базе может работать до 30 чел и больше. хотя конечно от 30 лучше даже в этом режиме переходить на 1с-сервер. В сети по share база и на 2-3х пользователях виснет и ломается бывает. 4-5 уже много 🙂

    Reply
  23. sss999

    скрипт не может переименовать таблицы ошибка компоненты на методе ренэйм, что не так?переименовывает с og на не og

    Reply
  24. sss999

    подскажите как вытащить данные таблицы в hex, программно не выходит, таблица с og на конце

    Reply
  25. sss999

    ну все равно спасибо за скрипт, хоть смог его запустить и что-то сделать

    Reply
  26. sss999

    как получить число подскажите ИндексБлокаЗаголовкаОписанияТаблицы

    Reply
  27. Artem108

    База вылетает с ошибкой «не обнаружена таблица «_ACCUMRGT17934». Развернул архив, там эта таблица есть. подскажите можно ли ее отдельно перенести в поврежденную базу? как это сделать?

    Reply
  28. msorina

    База вылетает без сообщений на выполнении команды

    FileDB.OpenTable(0,»CONFIGSAVE»);

    в предлагаемом Вами коде:

    FileDB=Новый(«AddIn.T1CDLib.DB1CD»);

    Состояние(«Чтение структуры файла»);

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

    FileDB.OpenTable(0,»CONFIGSAVE»);

    релиз платформы 8.3.11.2867, база была создана на релизе 8.3.11.2899.

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

    Reply

Leave a Comment

Ваш адрес email не будет опубликован. Обязательные поля помечены *