CITKIT.ru
3 терабайта свободного софта!
Logo    
IT-рынок Новости мира IT Океан(!) софта на CITKIT.ru Форумы Поступления в библиотеку Учебный центр Курилка
CitForum    CITForum на CD Море(!) аналитической информации! :: CITFORUM.RU
IT-консалтинг Software Engineering Программирование Open Source СУБД Безопасность Internet Сети Операционные системы Hardware

23.05.2005

Google
WWW CITForum.ru

Новости мира IT:

  • 11.05 - Intel создает свою группу по Open Source
  • 11.05 - Банк контролирует использование USB устройств при помощи DeviceLock
  • 11.05 - Microsoft устранила опасную дыру в Windows
  • 11.05 - "Корпорация ОСС" создает антимонопольный альянс операторов IP-телефонии
  • 11.05 - В Mac OS X найдены множественные уязвимости
  • 11.05 - "Билайн" запускает услугу "Мобильная почта"
  • 11.05 - Две критические уязвимости в браузере Firefox 1.0.3
  • 11.05 - IBM покупает начинающую Open Source-компанию Gluecode
  • 11.05 - Microsoft готова к битве с Open Source за школы
  • 11.05 - Sun завершит "открытие" Solaris в ближайшие 45 дней
  • 11.05 - Создатели браузера Firefox выпускают юбилейные монеты в честь 50 миллионов скачанных копий
  • 11.05 - Вышла пятая версия мобильной ОС от Microsoft
  • 11.05 - Поисковые движки умнеют быстрее, чем люди
  • 11.05 - Фишеры постоянно совершенствуются
  • 11.05 - Специалисты прогнозируют появление аналога Google Adsense от "Яндекс"
  • 06.05 - ICANN озаботилась проблемой торговых марок
  • 06.05 - Google патентует сортировку новостей
  • 06.05 - Intel готовит двуядерные процессоры второго поколения
  • 06.05 - Schoolforge-UK и OSC продвигают Open Source в школы
  • 06.05 - Новая версия рекламной программы подстрекает пользователей купить ПО для своего лечения
  • 06.05 - Microsoft продает ряд своих закрытых разработок
  • 06.05 - Google Labs анонсировал ускоритель интернета
  • 06.05 - Microsoft подвешивает пиратам "морковку"
  • 06.05 - В США входят в обиход "интеллектуальные" тележки для супермаркетов
  • 06.05 - Microsoft работает над аналогом PDF
  • 05.05 - Yahoo video search теперь доступен массам
  • 05.05 - Алмазы помогут бороться с хакерами
  • 05.05 - Интернет-охоту хотят запретить
  • 05.05 - Microsoft привлекает блоггеров для теста Longhorn
  • 05.05 - Основатель Red Hat предложил Стиву Джобсу помощь в решении проблемы с торговой маркой
  • 05.05 - Компьютерная система оргкомитета Кубка мира по футболу 2006 года пострадала от червя Sober
  • 04.05 - Cisco Systems представила многофункциональный продукт Adaptive Security Appliance 5500
  • 04.05 - Администрация Евросоюза поддержала идею всеевропейской интернет-библиотеки
  • 04.05 - Компьютерный вирус дарит билеты на чемпионат мира по футболу
  • 04.05 - Лаборатория Касперского: Обзор вирусной активности - апрель 2005
  • 04.05 - Microsoft хочет отсудить у россиянина два домена
  • 04.05 - Сделка между Lenovo и IBM завершена
  • 04.05 - Эпидемия червя Sober.p зафиксирована в Западной Европе
  • 04.05 - Panda Software публикует отчет о вирусной активности за апрель
  • 03.05 - Институт SANS обновил список наиболее опасных уязвимостей

    Архив новостей >>>


  • 2004 г.

    Delete from mytable; Commit:..
    или Восстановление данных в СУБД Interbase

    Вадим Павлов, Курганский Penguin

    Случилось страшное, кровь матери пролил сын обезумевший.

      (c)Кто-то древний

    Предисловие

    Данная статья написана на основе статей: "The Interbase On - Disk Structure" by Ann Harrison ; "Structure of a Data Page" by Paul Beach, а так же включает в себя мой горький опыт в удалении важных данных, а потом в их успешном восстановлении. Я никоим образом не собираюсь нарушать права ни выше перечисленных авторов, ни компаний, чьи зарегистрированные торговые знаки перечисленные в данной статье.

    Эта статья была написана Вадимом Павловым в 2004г. с соответствующим наложением авторских прав. Вы можете опубликовать её по своему усмотрению, единственным условием является опубликование данного абзаца.

    По любым вопросам, касающимся данной статьи можно связаться с автором по адресу: pvm _ job(at)mail.ru, либо пообщаться на форуме, в чате сайта penguin.photon.ru

    Концептуализация

    Итак, всё что можно было сделать плохого мы уже сами своими собственными руками сделали. Но не стоит сильно отчаиваться, в некоторых случаях можно помочь беде.

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

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

    Мы в данной статье будем рассматривать возможность восстановления данных в СУБД Interbase 6. x , Firebird 1. x для Windows (для других операционных систем возможны небольшие отличия в дисковой структуре).

    Сначала немного формализуем задачу.

    Что мы имеем:

    1. Реляционную базу данных с несколькими тысячами записей, которые необходимо восстановить.

    2. Устойчивое желание восстановить базу и немного терпения.

    Как вам, наверное, уже известно, сразу после удаления какой либо информации из базы данных Interbase , файлы базы не уменьшаются, значит, вся информация осталась, а были только удалены ссылки на место хранения необходимой нам информации (записей).

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

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

    Не нужно останавливать офис на неопределенный срок, достаточно просто скопировать базу поближе к себе и приступить к работе.

    Для удобства можно воспользоваться утилитой IBSurgeon Viewer (http://www.ib-aid.com/), а также любым клиентом sql для Interbase , вполне подойдет ibconsole , wisql , isql и т.д. А так же нам очень помогут статьи The InterBase On - Disk Structure By Ann Harrison , Borland Developers Conference San Diego 2000, Structure of a Data Page By Paul Beach .

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

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

    Итак, приступим.

    Дисковая структура базы данных Interbase

    Для понимания процесса восстановления и возможности такового изложим немного теории.

    База данных состоит из одного или нескольких файлов. Файл базы данных, в свою очередь, состоит из набора <страниц> (далее просто страниц) фиксированной длины, размер которых указывается при создании базы данных, каждый файл базы данных содержит в себе страницы одинакового размера. Стандартной является страница 4096 байтов. Достоверность данного утверждения можно проверить, поделив размер файла на размер страницы. У Вас получится количество страниц содержащихся в базе. Для удобства работы с каждой страницей в отдельности можно разрезать данный файл на множество файлов содержащих в себе только одну станицу, либо воспользоваться программой IBSurgeon Viewer .

    В Interbase используется несколько видов страниц:

    •  Страница-заголовок (Header page)

    •  Страница указателей (Pointer page)

    •  Страница учета транзакций (Transaction inventory page)

    •  Страница распределения места ( Space inventory page )

    •  Страница генераторов ( Generator page )

    •  Страница основного индекса ( Index root page )

    •  Станица индексов (Index page)

    •  Станица данных (Data page)

    Типы страниц определены в файле ods . h таким образом:

    /* Page types */

    #define pag_undefined 0

    #define pag_header 1 /* Database header page */

    #define pag_pages 2 /* Page inventory page */

    #define pag_transactions 3 /* Transaction inventory page */

    #define pag_pointer 4 /* Pointer page */

    #define pag_data 5 /* Data page */

    #define pag_root 6 /* Index root page */

    #define pag_index 7 /* Index (B-tree) page */

    #define pag_blob 8 /* Blob data page */

    #define pag_ids 9 /* Gen-ids */

    #define pag_log 10 /* Write ahead log information */

    #define pag_max 10 /* Max page type */

    Страница заголовок (Header page) это первый блок в первом файле в базе данных. Когда Interbase присоединяется к базе данных он считывает первый килобайт файла. Заголовок содержит в себе критичную информацию о базе данных. Она включает в себя номер версии дисковой структуры (On Disk Structure - ODS) и размер страницы. После того, как сервер Interbase установил, что версия дисковой структуры, которая используется в файле им поддерживается, он перечитывает страницу-заголовок, используя правильный размер страницы и узнает необходимую информацию, такую как имена и диапазон страниц, содержащихся во вторичных файлах базы данных, следующую доступную транзакцию и последнюю, интересующую нас, транзакцию.

    На последующем шаге ищется ядро системных таблиц и строится внутреннее представление базы данных.

    Страница указателей ( Pointer page )

    Страница-заголовок содержит информацию о месте положения первой страницы указателей для таблицы rdb$pages . Системная таблица rdb$pages позволяет interbase найти критичные страницы, включающие страницы данных для таблиц. Система читает первую страницу указателей и использует её для поиска первой страницы данных rdb$pages . Из неё затем можно найти страницы данных и индексов других системных таблиц.

    Таблица 1.

    Записи системной таблицы rdb$pages

    RDB$
    PAGE_NUMBER

    RDB$
    RELATION_ID

    RDB$
    PAGE_SEQUENCE

    RDB$
    PAGE_TYPE

    3

    0

    0

    4

    4

    0

    0

    6

    6

    1

    0

    4

    7

    1

    0

    6

    8

    2

    0

    4

    9

    2

    0

    6

    129

    0

    0

    9

    140

    0

    0

    3

    169

    0

    10

    3

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

    Страница учета транзакций (Transaction inventory page).

    Таблица rdb$pages содержит записи не только о страницах данных, а также о страницах учета транзакций. Подобно странице указателей страница учета транзакций состоит из простого заголовка, который включает в себя тип страницы и номер следующей страницы учета транзакций. Оставшаяся часть страницы является массивом двухбитовых записей, которые отражают состояние транзакций в системе. Ноль указывает на то, что транзакция не была начата, активна или <погибла> без подтверждения или отката. Единица указывает на то, что транзакция была подтверждена. Двойка указывает на то, что транзакция была опровергнута. Тройка указывает на то, что транзакция в состоянии <лимбо> (неопределенное состояние, которое существует в середине двухфазового подтверждения транзакции).

    Чтобы определить состояние транзакции Interbase использует номер транзакции, как индекс в массиве транзакций и просматривает состояние соответствующих битов. Алгоритм более сложный, так как зависит от заголовка страницы. В случае если одна транзакция проверяет состояние другой транзакции и обнаруживает, что она обозначена как активная, а фактически является <мертвой> - (<смерть>транзакции проверяется по средством проверки таблицы блокировки) - то она меняет состояние <мертвой> транзакции с активной на откаченную.

    Страница распределения места ( Space inventory page )

    Последней из страниц <хранителей очага> является страница распределения места. Страница распределения места показывает какие страницы являются распределенными (<зарезервированными>) и если она зарезервирована, то свободна ли она и насколько.

    Страница распределения места находится сразу за страницей-заголовком. Она подобно всем страницам имеет заголовок, в котором определен тип страницы. Остальная часть страницы - массив 1-битных кластеров, который соответствует страницам в базе данных. Каждая страница вне зависимости от типа включена в страницу распределения пространства (за исключением страницы-заголовка). Заголовок страницы распределения места не включает в себя указатель на следующую страницу распределения места, так же эти страницы не перечислены в таблице rdb$pages . Они расположены на определенных интервалах. Таким образом, Interbase вычисляет расположение следующей страницы в зависимости от размера страницы базы данных и длины заголовка.

    Когда страница добавляется в таблицу или индекс, Interbase меняет её состояние в странице распределения места. Ошибка "orphan page" возникает, когда сервер находится в середине процесса распределения новой страницы. Запись в страницу распределения места сделана, указанная страница выделена, но новая страница не была записана и осталась как <сирота>.

    Страница генераторов ( Generator page )

    Страница генераторов последняя из <простых> страниц. Страница генераторов состоит из заголовка и четырехбайтовых записей, которые представляют состояние генераторов. Индексом в этом массиве служит порядковый номер генератора. Таблица rdb$pages содержит в себе записи о страницах генераторов.

    Страница основного индекса ( Index root page )

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

    Страница индекса ( index page )

    Заголовок страницы индекса включает тип страницы и номер страницы следующей на данном уровне.

    Индексами называется древовидная структура. На странице основного индекса указывается верхняя страница индекса. Она содержит записи, указывающие на точки следующих уровней индексных страниц.

    Страница данных (Data page)

    Страница данных содержит следующие данные: записи, фрагменты записей, фрагменты, запасные версии, изменения, поля типа blob и относящиеся к данному полю структуры. Заголовок страницы, в частности, содержит тип страницы, номер отношения (relation , таблицы) и номер следующей страницы, содержащую данную таблицу. В отличие от других страниц, страницы данных содержат значимую структуру, следующую сразу за заголовком. Эта структура имеет название индекс записей. Последняя часть db_key записи является смещением в массиве индексов записей снизу страницы. Этот индекс содержит актуальное положение и размер сохраненной на странице строки таблицы.

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

    Эти структуры мы рассмотрим далее более подробно.

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

    Индекс содержит смещение, поэтому запись может перемещаться по странице без воздействия на её основной идентификатор - её db_key. Когда Interbase обнаруживает, что страница стала фрагментированной в следствии того что некоторые записи были удалены, то он сдвигает все оставшиеся данные вместе, делая одно большое пространство вместо небольших маленьких фрагментов. Это обычные действия базы данных.

    Как же выглядит строка таблицы на этом уровне? Во-первых, идет фиксированной длины заголовок, который включает в себя номер транзакции, которая создала эту версию записи и формат версии для этой записи. Если существует старая версия записи, то заголовок также содержит указатель на неё. В заголовке также указан тип записи: обычная запись, фрагментированная запись, фрагмент или поле blob . Маленькие blob -поля часто расположены на странице вместе с записью, к которой они относятся. Если запись фрагментирована, то в заголовке указывается на фрагмент.

    Последняя часть служебных данных в записи - добавление к записи переменной длины битов (кратной 8), определяющие значения NULL в соответствующих полях.

    Столбцы таблицы расположены в соответствии со значением rdb$field_id таблицы rdb$relation_fields, которая описывает их. Если порядок, определенный значением поля rdb$position отличается, то высокоуровневый механизм приводит их в соответствующий порядок. Высокоуровневая функция также смотрит на версию формата записи и использует ее для нахождения соответствующего формата в rdb$formats. Все записи будут переведены в наиболее подходящий формат во время перемещения из страницы в кэш записей. До тех пор, пока запись не будет изменена, она не будет перезаписана, даже если её формат устарел.

    Если запись является сохраненной ( back version ), её основная версия будет содержать флаг, который показывает какая из них является изменением. Изменения - это набор различий, которые могут быть применены к основной записи для создания её сохраненной ( back ) версии. Формат изменения очень похож на кодирование переменной длины, с байтами указывающим количество заменяемых символов и количество сохраняемых символов.

    Записи не фрагментируются до тех пор, пока сжатый размер данных меньше размера страницы. Когда запись модифицируется её сжатый размер может увеличиваться, до тех пор, пока не останется места на странице, в данном случае она будет фрагментироваться. Фрагментация значительно влияет на производительность, так как чтение фрагментированной записи требует выборку, как минимум двух страниц. Запись фрагментированных строк может требовать четыре или более страниц для использования стратегии <точной записи>, которая требует, чтобы изменения на странице были записаны в соответствующем порядке.

    Страница BLOB ( Data page )

    Страницы, полностью занятые двоичными данными ( BLOB ), можно при определённых условиях выделить в отдельный тип страниц БД, которые не отражаются на странице указателей.

    Также страница двоичных данных может быть страницей указателей на другие страницы двоичных данных. Для каждого созданного поля BLOB создаётся запись, содержащая информацию о расположении данных поля и данные о содержимом, которые могут быть полезны при чтении. Механизм хранения таких полей определяется их размером и бывает трёх типов (0,1,2).

    •  Механизм 0 . Поле умещается на одной странице БД вместе с записью.

    •  Механизм 1 . Когда поле не умещается на одной странице БД вместе с записью, поле записывается в специализированные страницы, а в поле двоичных данных на странице с остальными полями данных записи будет помещен массив указателей на занятые полем страницы

    •  Механизм 2. Когда места на начальной странице не хватает даже для того, чтобы записать туда массив указателей, InterBase создаст страницу (страницы) указателей на страницы с полем BLOB.

    Восстановление информации

    В самом простом случае для восстановления данных нам нужно знать лишь структуру страниц данных. Всю остальную полезную информацию мы сможем получить с помощью sql запросов к системным таблицам Interbase , что существенно ускорит и упростит процесс восстановления информации и, соответственно, продлит и укрепит наш сон.

    Подробный формат страницы данных и записи

    Рассмотрим формат страницы данных и записи более подробно.

    Выборочно информацию возьмем из файла ods . h ( on disk structure ) из поставки Interbase ( firebird ) и опишем ее более подробно.

    /* Page types */

    #define pag_data 5 /* Data page */

    Указывается, что страница данных идентифицируется номером 5.

    #ifdef _CRAY

    #define MIN_PAGE_SIZE 4096

    #else

    #define MIN_PAGE_SIZE 1024

    #endif

    #define MAX_PAGE_SIZE 16384

    #define DEFAULT_PAGE_SIZE 4096

    В данном листинге определяются размеры страницы: её максимальный и минимальный размер, а так же размер по умолчанию.

    /* Basic page header */

    Основной заголовок страницы

    typedef struct pag {

    SCHAR pag_type;

    SCHAR pag_flags;

    USHORT pag_checksum;

    ULONG pag_generation;

    ULONG pag_seqno; /*WAL seqno of last update*/

    ULONG pag_offset; /*WAL offset of last update*/

    } *PAG;

    Определяется: тип страницы, флаги, контрольная сумма, номер последней измененной последовательности и смещение последнего изменения.

    /* Data Page */

    Определяется заголовок страницы данных

    typedef struct dpg {

    struct pag dpg_header;

    SLONG dpg_sequence;

    USHORT dpg_relation;

    USHORT dpg_count;

    struct dpg_repeat

    {

    USHORT dpg_offset;

    USHORT dpg_length;

    } dpg_rpt [1];

    } *DPG;

    Сначала идет стандартный заголовок страницы, далее следует номер последовательности в отношении, номер отношения, количество записей на странице. Далее следует повторяющаяся структура { смещение, длина } фрагмента записи.

    /* Record header */

    Заголовок записи

    typedef struct rhd {

    SLONG rhd_transaction;/* transaction id */

    SLONG rhd_b_page; /* back pointer */

    USHORT rhd_b_line; /* back line */

    USHORT rhd_flags; /* flags, etc */

    UCHAR rhd_format; /* format version */

    #ifdef _CRAY

    UCHAR rhd_pad [7];

    #endif

    UCHAR rhd_data [1];

    } *RHD;

    В заголовке записи определен номер транзакции, указатель на старую версию записи, флаги, версию формата записи и непосредственно данные.

    Так же из файла ods . h можно узнать структуру фрагментированных записей и структуру записей поля blob . Но в данной статье мы не будем их рассматривать.

    Далее определяются флаги записей

    # define rhd _ deleted 1

    Запись логически удалена

    #define rhd_chain 2

    Запись является старой версией

    #define rhd_fragment 4

    Запись является фрагментом

    #define rhd_incomplete 8

    Запись неполная

    #define rhd_blob 16

    Поле типа blob

    #define rhd_delta 32

    Предыдущая версия, различия только

    #define rhd_large 64

    Объект является большим

    #define rhd_damaged 128

    Объект известен , как поврежденный

    #define rhd_gc_active 256

    Мусор, мертвая версия записи

    Как говорилось, ранее данные в записях сжаты методом кодирования переменной длины ( RLE ). Суть метода заключается в том, что положительное число указывает на количество следующих байт, которые непосредственно следует прочитать, отрицательное же число указывает, что следующий байт нужно повторить abs ( n ) (где abs - модуль числа) раз.

    Заголовок хранит информацию о транзакции, которая требуется для реализации multi - generational архитектуры, в нормальной записи заголовок будет только содержать указатель на старую версию.

    После заголовка и перед данными идет вектор нулевых бит на каждое поле (добитое до 8 (битовой) байтовой границы) в таблице. Если флаг установлен, тогда поле равно нулю, пока данные установлены в 0 для улучшения компрессии. Это означает что заголовок состоит из эффективной длины 16 байт и 3 байта были добавлены для выравнивания. Байты для нулевого битового вектора добавляются по необходимости, в зависимости от количества полей, определенных в таблице.

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

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

    Напомню вам, что на платформе intel при записи числа типа word (два байта), сначала записывается младший байт, а затем старший, например число 0 x 5684 будет представлено на диске, как 84:56. Аналогично сохраняются и числа типа long .

    Формат даты является необычным по сравнению со стандартными типами записи дат, поэтому немного остановимся на его описании.

    Для хранения даты и времени в Interbase существует тип date, его внутреннее представление таково. Это запись из двух 32-разрядных знаковых целых чисел. В первом числе хранится число дней, прошедших с 17 ноября 1858, а во втором - время в десятых долях миллисекунды, прошедшее после полуночи.

    Для перевода в стандартный тип Delphi - TDateTime, который объявлен как TDateTime = type Double, где целая часть - это число дней, прошедших с 30 декабря 1899, а дробная часть - время, прошедшее после полуночи (.0 = 0:00; .25 = 6:00; .5 = 12:00; .75 = 18:00) можно воспользоваться простой формулой

    DateTime := Days - IBDateDelta + MSec10 / MSecsPerDay10, где

    Days - количество дней в формате Interbase ;

    IBDateDelta = 15018 - разница в днях между датами Delphi и Interbase;

    MSec 10 - время в десятых долях миллисекунды, прошедшее после полуночи;

    MSecsPerDay10 = Количество миллисекунд в сутках * 10

    На данный момент мы в достаточной степени узнали необходимую информацию о том, каким образом и где хранится информация в препарируемой нами базе данных. Изучив подробно все структуры используемые СУБД было бы возможно написать программу и воочию посмотреть и восстановить все данные своими руками. Но, как говорится, <Кесарю - кесарево>, я же предпочитаю воспользоваться стандартной программной isq ( wisq , кому как нравится) и движком interbase (ведь не зря его писали?) если, конечно база данных не повреждена, и тем самым ускорить процесс восстановления информации.

    SQL- запросы

    Далее мы рассмотрим sql -запросы, которые необходимы нам для восстановления утерянной информации.

    select rdb$relation_fields.rdb$field_name, rdb$relation_fields.rdb$field_id, rdb$fields.rdb$field_length, rdb$types.rdb$type_name from rdb$relation_fields left join rdb$fields on rdb$relation_fields.rdb$field_source= rdb$fields.rdb$field_name left join rdb$types on rdb$types.rdb$type=rdb$fields.rdb$field_type where (rdb$relation_name=' MYTABLE ') and (rdb$types.rdb$field_name= 'RDB$FIELD_TYPE')

    Данный запрос дает нам ответ на один из главных вопросов, как расположены поля в записи таблицы MYTABLE , какой имеют размер и тип

    Пример выборки :

    RDB$
    FIELD_NAME

    RDB$
    FIELD_ID

    RDB$
    FIELD_LENGTH

    RDB$
    TYPE_NAME

    field 1

    0

    4

    long

    field2

    1

    2

    float

    field3

    3

    8

    double

    field4

    4

    1

    varying

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

    Осталось только узнать в каких страницах расположена таблица, которую мы пытаемся восстановить.

    select rdb$relation_id,rdb$relation_name, RDB$PAGE_NUMBER, rdb$page_type from rdb$pages left join RDB$relations on rdb$pages. RDB$RELATION_ID=RDB$relations.RDB$RELATION_ID where rdb$relation_name=' MYTABLE ';

    Пример выборки:

    RDB$
    RELATION_ID

    RDB$
    RELATION_NAME

    RDB$
    PAGE_NUMBER

    RDB$
    PAGE_TYPE

    145

    MYTABLE

    198

    4

    145

    MYTABLE

    199

    6

    В первой колонке указан номер отношения (таблицы), во второй название таблицы, в третьей страницы, на которых расположена таблица, а в четвертой тип таблицы.

    На самом деле, <увы и ах>, мы только <добыли> из базы номера страниц указателя и индекса, а не полностью список всех страниц. Так что, засучим рукава и будем работать далее. Страница индексов для нас никоем образом не важна, а формат страницы указателя был вкратце описан выше.

    Остановимся на нем более подробно.

    typedef struct ppg {
       struct pag ppg_header;
       SLONG ppg_sequence; /* Sequence number in relation */
       SLONG ppg_next; /* Next pointer page in relation */
       USHORT ppg_count; /* Number of slots active */
       USHORT ppg_relation; /* Relation id */
       USHORT ppg_min_space;/* Lowest slot with space available */
       USHORT ppg_max_space;/* Highest slot with space available */
       SLONG ppg_page [1]; /* Data page vector */ } *PPG;  
    #define ppg_eof 1 /* Last pointer page in relation */

    В стандартном заголовке для нас особо интересно поле flag , если как описано выше, оно установлено в <1>, то это значит что таблица указателей является последней для рассматриваемого отношения (таблицы), и соответственно мы можем узнать все необходимые нам данные.

    За стандартным заголовком страницы, идет заголовок страницы указателей, где соответственно указывается: номер данной страницы, в последовательности страниц указателя для данного отношения (таблицы); номер следующей страницы для данного отношения; количество активных слотов (то есть записей о том, какие страницы используются); номер отношения (таблицы); наименьший доступный слот и максимальный доступный слот.

    Далее идет вектор данных, в котором непосредственно и перечислены страницы.

    Всё вышеописанное можно наглядно посмотреть с помощью программы IBSurgeon Viewer .

    Итак, что мы знаем в данный момент:

    •  структуру таблицы - каким образом расположены в ней поля и их размер;
    •  номера страниц данных, в которых находится наша таблица;
    •  структуру страниц данных.

    Таким образом, у нас выполнены необходимые и достаточные условия, чтобы попробовать восстановить утерянные данные.

    Восстановление данных

    И так мы можем приступать к самому ответственному этапу. Для удобства работы можно порезать файл базы данных на множество страниц и вычленить страницы с необходимой нам таблицей. Для начала пусть это будет любая таблица с текстовыми данными, например справочник товаров и т.д. Просмотрев его любым текстовым редактором можно заметить, что в данном файле находятся утерянные текстовые данные. Но возникает другой вопрос, как эти данные вытащить из базы, если заголовок со смещением и размером записи утерян навсегда. Возможно придумать массу алгоритмов с помощью которых можно восстановить утерянные данные, я предлагаю, на мой взгляд, самый простой, да и по вычислительным возможностям современных компьютеров восстановление происходит относительно быстро. В качестве примера данного утверждения могу сказать, что восстановление 2000 записей (не текстовая таблица) на Athlon XP 2000, программой написанной на Delphi , заняло порядка 10 секунд.

    Суть алгоритма состоит в том, что нам известно следующее:

    •  размер записи в байтах;
    •  записи начинаются с конца страницы и сжаты методом rle ;
    •  записи расположены не по всей странице;
    •  на любые данные, находящиеся в таблице, можно наложить соответствующие ограничения.

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

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

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

    При проверке стоит учитывать несколько факторов, которые напрямую зависят от предметной области базы данных:

    •  Если первичным ключом таблицы является поле с автоинкриментом, то соответственно оно не должно быть более чем значение генератора, так же, если не определено иное оно не может быть отрицательным;

    •  Даты, если это, например, простенькая складская программа, не могут быть в далёком прошлом и далёком будущем;

    •  Цена на товар не может быть отрицательной либо слишком большой;

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

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

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

    В результате проделанной работы мы получаем из базы всё что нужно.

    Для простоты восстановления можно просто приостановить работу всех триггеров и с помощью sql запросов добавить недостающие данные.

    ГОТОВО!!!!
     


    ХАЙВЕЙ - лучший российский хостинг-провайдер: хостинг, регистрация доменов, услуга Ваша@почта, поддержка 24 часа


    NetPromoter - единственный российский профессиональный комплекс программ и сервисов для раскрутки сайта и интернет-статистики


    STSS - известный поставщик надежных серверных решений различного назначения на платформе Intel (Xeon) и AMD.


    5-55: the ITIL company. Практический опыт и теоретические знания на лучших семинарах по ITIL и процессам ITSM.


    Подписка на новости IT-портала CITForum.ru
    (библиотека, ftp-архив CITKIT.ru)

    Новые поступления в on-line библиотеку:

    28 апреля

  • Выбор первого дистрибутива Linux: Пособие для начинающих
  • Обфускация и защита программных продуктов
  • Анализ и оптимизация циклов с помощью производящих функций
  • Стратегии объектно-реляционного отображения: систематизация и анализ на основе паттернов

    26 апреля

  • Business Intelligence обещает значительный рост в 2005 году
  • Десять основных тенденций 2005 года в области Business Intelligence и Хранилищ данных
  • Управление эффективностью бизнеса и предсказуемость
  • Увеличение эффективности бизнеса: пять ошибок управления, которых следует избегать
  • Потребность в организационных данных: модель комплексного управления эффективностью бизнеса
  • Технология Хранилищ данных для государственных учреждений
  • Оцените, насколько совершенно ваше Хранилище данных

    21 апреля

  • Исполнение моделей при помощи виртуальной машины
  • Параллельные алгоритмы компьютерной алгебры
  • От стандарта до стандарта (о стандартизации оптических разъемов)
  • За штурвалом IP-станции

    Продолжение дискуссии читателей:

  • Линукс и пользователи, или что мне не нравится в Linux
  • Еще один взгляд на альтернативные ОС (и софт для них)
  • О некомпетентности пользователя Windows
  • Переписка Долгачева В.С. и Монахова В.В.

    19 апреля

  • Межпротокольный шлюз NAT-PT с функциями DNS-ALG и FTP-ALG для обеспечения взаимодействия между сетями IPv4 и IPv6
  • Рефакторинг архитектуры программного обеспечения: выделение слоев
  • Комбинаторика слов и построение тестовых последовательностей
  • Функциональное тестирование Web-приложений на основе технологии UniTesK

    14 апреля

  • Как организовать двойную парольную защиту данных в Oracle
  • Деревянный интерфейс

    Продолжение дискуссии читателей:

  • Microsoft против мира
  • Впечатления от прочитанного

    12 апреля

  • Крупные проблемы и текущие задачи исследований в области баз данных
  • Глава 2 из книги Т.Кайта "Oracle для профессионалов"Архитектура

    Дискуссия читателей о Linux и Windows:

  • Деньги правят миром, и у кого их больше, тот и прав!
  • О злокозненности некомпетентных пользователей, или почему я не люблю ограниченных пользователей Windows

    7 апреля

  • О доблести Билла Гейтса, или почему Windows лучше, чем LINUX или Mac OS
  • Витая пара - все ли так просто?!
  • Выбираем сервер печати
  • Один слой хорошо, а два - лучше (о пишущих DVD-приводах)

    5 апреля

  • Использование Caché SQL Gateway
  • Глава 19 из книги Т.Кайта "Oracle для профессионалов"Хранимые процедуры на языке Java
  • Что такое PostgreSQL?
  • Обновлен PostgreSQL FAQ

    31 марта

  • Использование Веб-сервисов в Caché
  • Защита на уровне строк (Oracle)
  • Секции в реальном мире

    29 марта

  • Разработка успешных приложений для Oracle - первая глава из книги Тома Кайта "Oracle для профессионалов"
  • Web-сервисы: растущие опасения (мнение аналитиков IDC)
  • Технология OLAP - мощная альтернатива электронным таблицам
  • Какой модной стала подготовка отчетности

    24 марта

  • Многоверсионность данных и управление параллельными транзакциями
  • Исключение из правил. Опыт разработки и внедрения финансовой корпоративной системы
  • Обнаружение компрометаций ядра Linux с помощью gdb
  • Корпоративная сервисная шина - "бюджетный" подход к решению задач интеграции
  • Сервис-ориентированная архитектура
  • Бизнес-процессы и XML

    22 марта

  • Доступно. И точка! (обзор точек беспроводного доступа)
  • Коммутаторы Fast/Gigabit Ethernet для "большой" сети
  • Push to Talk: нажми на кнопку и ...говори
  • Сети нового поколения и технология softswitch

    17 марта

  • Часто задаваемые вопросы о proxy (proxy FAQ)
  • Самонастраивающаяся база данных: управляемые приложения и настройка SQL
  • Еще раз о волоконных трассах
  • Настраиваем русский Unicode в FreeBSD-5.3.

    10 марта

  • Еще не сказанное о волоконной оптике
  • Wi-Fi на службе оператора
  • Пора менять платформу?
    (о сокетах LGA775 и PGA478)

    Oracle:

  • Детальный аудит для практических целей
  • Шифруем свои ресурсы данных

    3 марта

  • Требования к проекту. Классификация - первый шаг к пониманию
  • Gtk vs. Qt: драки не будет
  • Управление бизнесом "по максимуму": BPM для финансовых учреждений
  • Реализация решения по управлению эффективностью бизнеса
  • Новые SerialATA-винчестеры
  • Карман для сервера

    1 марта

  • Выбрать корпус - нет ничего проще?
  • Создание виртуальной сети с удаленной загрузкой узлов
  • Текущее состояние и перспективы развития рынка интеграционных технологий
  • Интеграция корпоративной информации: новое направление
  • Архитектурные подходы к консолидации

    24 февраля

  • Каждому проекту своя методология
  • Императив интеграции
  • Безопасность IP-телефонии - полевые зарисовки
  • О злокозненности Билла Гейтса, или почему я не люблю Windows

    22 февраля

  • Oracle10: шифруем данные
  • В версии Oracle10 "виртуальные частные базы данных" данных стали избирательнее
  • Каждому (пользователю) свое (данное в таблице)
    Часть 1
    Часть 2
  • Ускоряем интернет
  • Сетевая аутентификация на практике
  • В фокусе Microsoft Virtual Server 2005

    17 февраля

    Открыт новый раздел
    Все об Open Source

    Все новости >>>



  • IT-консалтинг Software Engineering Программирование Open Source СУБД Безопасность Internet Сети Операционные системы Hardware

    Информация для рекламодателей PR-акции, размещение рекламы - pr@citforum.ru, тел. +7 095 4119920 Пресс-релизы - manager@citforum.ru
    Послать комментарий
    Информация для авторов
    Rambler's Top100 TopList liveinternet.ru: показано число просмотров за 24 часа, посетителей за 24 часа и за сегодня This Web server launched on February 24, 1997
    Copyright © 1997-2000 CIT, © 2001-2004 CIT Forum
    Внимание! Любой из материалов, опубликованных на этом сервере, не может быть воспроизведен в какой бы то ни было форме и какими бы то ни было средствами без письменного разрешения владельцев авторских прав. Подробнее...