このページは機械翻訳されています。英語の原文をお読みください。 English

IBSurgeon ライブラリ

InterBase および Firebird リカバリガイド

注意: この文書は、Alexey Kovyazin と Serg Vostrikov によって書かれた書籍「The InterBase World」の章です。

書籍「The InterBase World」のデータベース修復に捧げられた章。

1. このガイドの歴史

ロシア語の書籍「The InterBase World」は2002年9月に出版されました。

発行部数は3000部でした。3ヶ月後には完売し、2003年4月に改訂版が5000部発行されました。

現在、ロシア最大のオンライン書店でトップに位置しており、間もなく完売する見込みです。

本書の著者は、IBSurgeon の開発者であり、ロシアで著名な InterBase スペシャリストである Alexey Kovyazin と、Devrace 社 (www.devrace.com) の CEO である Serg Vostrikov です。

面白いことに、InterBase に特化した書籍は英語では一冊も出版されていません!

何千人もの開発者が InterBase と Firebird を使用し、さまざまなカンファレンスでこのトピックについて議論しています (こちらをご覧ください: リンク)。

InterBase 開発者のコミュニティは、平均して数万人規模です。さまざまな国での InterBase 書籍に対する強い需要は、InterBase コミュニティが本当に大きいことを証明しています。

10000部の版が Amazon.com から1ヶ月で完売するという事実に、ビール1ケースを賭けてもいいでしょう。しかし、出版社の人々は「すべてを知っており」、誰も InterBase に関する本を買わないと確信しています。それは本当に残念なことです。

ここでは、InterBase/Firebird データベースのリカバリに捧げられた本書の一章の草稿を提供したいと思います。

2. InterBase/Firebird データベースのリカバリ方法

2.1. データベース破損の主な原因の概要

残念ながら、あらゆる情報ストアが破損し、そこから一部の情報が失われる可能性は常にあります。データベースもこの規則の例外ではありません。この章では、InterBase データベースの破損につながる主な原因、データベースの修復方法、およびデータベースからの情報抽出について考察します。また、データベースからの情報損失の可能性を最小限に抑えるための推奨事項と予防策についても学びます。

まず第一に、データベース修復について話す場合、「データベース破損」の概念を明確にする必要があります。データベースは通常、情報の抽出または変更を試みたときにエラーが発生したり、抽出された情報が失われたり、不完全であったり、まったく正しくなかったりする場合に、損傷していると呼ばれます。データベースの破損が隠れており、特別な機能によるテストによってのみ発見される場合もありますが、データベースに接続できない、調整されたプログラムクライアントが奇妙なエラーを表示する (データベースに対して操作が実行されていない場合)、またはバックアップコピーからデータベースを復元できないなど、実際のデータベース破損もあります。

2.2. データベース破損の主な原因は次のとおりです:

  • サーバーコンピュータの異常終了、特に電力供給の中断。IT業界にとってこれは本当に厄介な問題であり、サーバーに無停電電源装置を設置する必要性について改めて注意を促す必要はないと思います。
  • サーバーコンピュータの欠陥や障害、特に HDD (ハードディスクドライブ)、ディスクコントローラ、コンピュータのメインメモリ、Raid コントローラのキャッシュメモリ。
  • マルチクライアントデータベースでの1人以上のユーザーによる不適切な接続文字列 (バージョン 6.x より前)。TCP/IP 経由で接続する場合、データベースへのパスは、サーバー名: ドライブ:/パス/データベース名 /UNIX プラットフォーム上のサーバーの場合は servername: /パス/データベース名 /、NETBEUI プロトコルに従って \\servername\drive:\path\databasename と指定する必要があります。データベースが配置され、サーバーが実行されているコンピュータからデータベースに接続する場合でも、servername を localhost に置き換えた同じ行を使用する必要があります。接続行でマップされたドライブを使用することはできません。これらの規則のいずれかに違反すると、サーバーは異なるデータベースで動作していると見なし、データベースの破損が保証されます。
  • サーバーの実行中にデータベースへのファイルコピーまたはその他のファイルアクセスを行うこと。「shut-down」コマンドの実行や通常の方法でのユーザーの切断は、スイープ間隔が「0」に設定されていない場合、サーバーがデータベースに対して何も行っていないことを保証するものではありません。ガベージコレクションが実行される可能性があります。通常、ガベージコレクションは最後のユーザーがデータベースから切断した直後に実行されます。通常は数秒かかりますが、その前に多くの DELETE または UPDATE 操作がコミットされた場合、プロセスが長くなる可能性があります。
  • 不安定な InterBase サーバーバージョン 5.1-.5.5 の使用。Borland 社は、これらのサーバーにいくつかのエラーがあり、安定したアップグレード 5.6 は、認定された InterBase 6 の出力がサイト上でサーバー 5.1-5.5 のすべてのクライアントに対してフリーランニングモードになった後にのみ削除されたことを公式に認めました。
  • データベースファイル (データベースではありません!) のサイズ制限を超えること。InterBase 6 より前のバージョンおよび一部の InterBase 6 ベータ版では、データベースファイルの制限は 4Gb であり、InterBase 6.5 および Firebird のすべてのリリース (1.0、1.5、2.0、2.1) では 32Tb です。データベースサイズが制限値に近づいたら、追加ファイルを作成する必要があります。
  • データベースでの作業中の空きディスク容量の枯渇。
  • バージョン 6.0.1.6 未満の Borland InterBase サーバーの場合 - Borland InterBase R & D によって定義されたジェネレータ数の制限を超えること (表1を参照)。
バージョン ページサイズ=1024 ページサイズ=2048 ページサイズ=4096 ページサイズ=8192
6より前 248 504 1016 2040
6.0.x 124 257 508 102

表1: 初期の InterBase バージョンにおけるジェネレータの臨界数

• すべての Borland InterBase サーバーの場合 - バックアップ/リストアを実行せずに許容されるトランザクション数を超えること。最後の作成以降にデータベースで発生したトランザクション数は、ユーティリティ gstat をキー - h- パラメータ NEXT TRANSACTION ID で呼び出すことで知ることができます。これはトランザクションの望ましい数量になります。Ann W.Harrison によると、トランザクションの臨界数はページサイズに依存し、次の値になります (表2を参照):

データベースのページサイズ トランザクションの臨界数
1024 バイト 131 596 287
2048 バイト 265 814 016
4096 バイト 534 249 472
8192 バイト 1 071 120 384

表2: Borland InterBase サーバーにおけるトランザクションの臨界数

上記の Borland InterBase サーバーの制約は、既に歴史となった最も初期のバージョン 0.x を除き、Firebird サーバーには適用されません。最終バージョンの Firebird 1.0 または InterBase 6.5-7.x を使用している場合は、ポイント 5、6、8、9 について心配する必要はなく、他の原因に集中する必要があります。ここでは、最も頻繁に発生するものを詳しく見ていきましょう。

2.3. 電源障害

サーバーの電源が切れると、データ処理のすべてのアクティビティが、最も予期しない (そしてマーフィーの法則によると危険な) 場所で中断されます。その結果、データベース内の情報が歪んだり失われたりする可能性があります。最も単純なケースは、サーバーの緊急シャットダウンの結果として、クライアントアプリケーションからのすべてのコミットされていないデータが失われる場合です。電源障害後の再起動時に、サーバーはデータを分析し、どのクライアントにも関連しない不完全なトランザクションに気づき、これらの「デッド」トランザクションの範囲内で行われたすべての変更をキャンセルします。実際、このような動作は正常であり、InterBase 開発者によって最初から想定されています。

ただし、電力供給の中断は、常にこのような軽微な損失のみを伴うとは限りません。電力供給の中断時にサーバーがデータベース拡張を実行していた場合、データベースファイルに孤立ページ (物理的に割り当てられ、ページインベントリページ (PIP) に登録されているが、データ書き込みが不可能なページ) が存在する可能性が高くなります。孤立ページについて詳しくは、「InterBase データベースの構造」の章をご覧ください。

修復および変更ツール gfix (以下で説明します) のみが、データベースファイル内の孤立ページに対処できます。実際、孤立ページはディスク容量の不必要な消費につながりますが、それ自体はデータ損失や破損の原因ではありません。

停電はより深刻な損害をもたらします。例えば、電源を切って再起動した後、コミット済みのデータを含む大量のデータが失われる可能性があります(「commit transaction」コマンドが実行された追加や変更の後)。これは、確定済みのデータがディスク上のデータベースファイルに直接書き込まれないために起こります。その代わりに、オペレーティングシステム(OS)のファイルキャッシュがこの目的のために使用されます。サーバープロセスはOSにデータ書き込みコマンドを渡します。その後、OSはサーバーに対してすべてのデータがディスクに保存されたと保証しますが、実際にはデータはファイルキャッシュに格納されています。OSはこれらのデータをディスクにフラッシュすることを急ぎません。なぜなら、メインメモリにまだ十分な空きがあると考え、メインメモリが満杯になるまでディスクへの低速な書き込み操作を延期するからです。

2.4. 強制書き込み - 諸刃の剣

この状況に対処するために、InterBase 6ではデータ書き込みモードの設定が提供されています。このパラメータは強制書き込み(FW)と呼ばれ、ON(同期)とOFF(非同期)の2つのモードがあります。FWモードは、InterBaseがディスクとどのように通信するかを定義します。FWがオンの場合、同期ディスク書き込みの設定が有効になり、確定済みのデータはcommitコマンドの直後にディスクに書き込まれ、サーバーは書き込み完了を待ってから処理を続行します。FWがオフの場合、InterBaseはトランザクションコミットのコマンドの後にデータをディスクに書き込むことを急がず、このタスクを並列スレッドに委任し、メインスレッドはディスクへの書き込みが完了するのを待たずにデータ処理を続行します。同期書き込みモードは最も慎重なモードの1つであり、可能性のあるデータ損失を最小限に抑えますが、パフォーマンスの低下を引き起こす可能性があります。非同期書き込みモードは、大量のデータが失われる可能性を高めます。最大のパフォーマンスを達成するために、通常はFW Offモードが設定されます。しかし、電源遮断の結果として、非同期書き込み中は同期書き込みよりもはるかに多くのデータが失われます。書き込みモードを設定する際には、予期せぬ電源遮断が発生した場合に、数パーセントのパフォーマンスが数時間の作業よりも重要かどうかを判断する必要があります。

非常に多くの場合、ユーザーはInterBaseに対して不注意です。小規模な組織はあらゆる些細なことで節約し、多くの場合、DBMSサーバーとさまざまなサーバープログラム(サーバーだけでなく)も設定されているコンピューターサーバーで節約します。ハングアップした場合、人々は長く考えずにRESETを押します(これは1日に数回発生します)。InterBaseは他のDBMSと比較してこのような操作に対して非常に安定しており、緊急再起動後すぐにデータベースでの作業を開始できますが、そのような使用は望ましくありません。孤立ページの数が増加し、障害再起動の結果としてデータ間の接続が失われます。

これは長期間続く可能性がありますが、遅かれ早かれ終わりが来ます。PIPやジェネレータのページの中に損傷したページが現れたり、データベースヘッダーページが破損したりすると、データベースは二度と開けなくなり、有用な情報を1バイトも抽出できない大きな個別データの塊になる可能性があります。

2.5. ハードディスクの破損

ハードディスクの破損は、データベースの重要なシステムページの欠落や、残っているページ間のリンクの破損につながります。このような破損は最も困難なケースの1つです。なぜなら、ほとんどの場合、データベースを復元するために低レベルの介入が必要になるからです。

2.6. データベース設計の誤り

データベース開発者が犯すいくつかの誤りについて知っておく必要があります。これらの誤りは、バックアップコピー(gbakプログラムによって作成される*.gbkファイル)からのデータベース復元を不可能にする可能性があります。まず第一に、データベースレベルでの制約の不注意な使用です。典型的な例はNOT NULL制約です。レコード数で満たされたテーブルがあると仮定しましょう。ここで、ALTER TABLEコマンドを使用してこのテーブルにもう1つの列を追加し、それが非定義値NULLを含んではならないことを指定します。次のようなものです:

ALTER TABLE sometable Field/INTEGER NOT NULL

そしてこの場合、予想されるようなサーバーエラーは発生しません。このメタデータの変更はコミットされ、エラーや警告メッセージを受け取ることはなく、この状況が正常であるという錯覚を作り出します。

しかし、データベースをバックアップし、バックアップコピーから復元しようとすると、復元フェーズでエラーメッセージを受け取ります(NOT NULL制約を持つ列にNullが挿入されるため、復元プロセスが中断されます)。(Craig Stuntzによる重要な注記 - InterBase 7.1バージョンでは、復元中に制約がデフォルトで無視され(これはコマンドラインスイッチで制御できます)、ほぼすべての非破損バックアップを復元できます。バックアップ作成後にテスト復元を行うことは常に良い考えですが、この問題はバージョン7.1ではほぼ解消されるはずです。)このバックアップコピーは復元できません。復元が既存のデータベースと同じ名前のファイルに向けられていた場合(復元中に既存のデータベース作業ファイルが上書きされていた場合)、すべての情報を失うことになります。

これは、NOT NULL制約がシステムトリガーによって実装されており、到着するデータのみをチェックするという事実に関連しています。バックアップコピーからのデータの復元中、データは作成されたばかりの空のテーブルに挿入されます。ここで、NOT NULL制約を持つ列に許容されないNULLが見つかる可能性があります。

一部の開発者は、このようなInterBaseの動作は正しくないと考えていますが、別の動作ではNOT NULL制約を持つフィールドをデータベーステーブルに追加できなくなります。

デフォルトで必要な値と作成時点でのその値による充填に関する問題は、Firebirdアーキテクトによって広く議論されましたが、プログラマーが明らかにアルゴリズムに従ってそれを充填するつもりであり、それはかなり複雑でおそらく反復的であるという事実のために受け入れられませんでした。しかし、前の反復で無視されたレコードと未充填のレコードを区別できるかどうかの保証はありません。

同様の問題は、接続時にデータベースへの正しくないパスを設定したことによるガベージコレクションの障害(破損原因3)や、サーバーがデータベースで作業しているときのデータベースファイルへのファイルアクセス(破損原因4)によって引き起こされる可能性があり、一部のテーブルにNullで完全に満たされたレコードが現れる可能性があります。これらのレコードは整合性制御制限に対応していないため検出が非常に困難で、Select演算子はそれらを認識しませんが、バックアップコピーには含まれます。この理由で復元が不可能な場合は、gfixプログラム(下記参照)を実行し、非インデックスフィールドを検索条件として使用してこれらのレコードを見つけて削除し、その後バックアップコピーを作成してデータベースを復元することを再試行する必要があります。結論として、データベース破損の原因は多数あり、最悪の事態-つまり何らかの理由でデータベースが損傷すること-に常に備える必要があると言えます。また、貴重な情報を復元して保存する準備も必要です。そして今、InterBaseデータベースのセキュリティを保証する予防策と、損傷したデータベースを修復する方法を検討します。

2.7. InterBaseデータベース破損の予防策

データベースの破損を防ぐために、常にバックアップコピーを作成する必要があります(バックアップについて詳しく知りたい場合は、「バックアップと復元」の章を参照してください)。これはデータベース破損に対する最も信頼できる方法です。バックアップのみがデータベースセキュリティの100%の保証を提供します。上記で説明したように、バックアップの結果として役に立たないコピー(復元できないコピー)を取得する可能性があるため、コピーからのデータベースの復元はスクリプトを上書きして実行してはならず、バックアップは明確なルールに従って実行する必要があります。第一に、バックアップはできるだけ頻繁に実行する必要があり、第二に、連続的である必要があり、第三に、バックアップコピーは復元可能性をチェックする必要があります。

多くの場合、バックアップとは、かなり頻繁に、例えば24時間に1回、バックアップコピーを作成する必要があることを意味します。データベースのバックアップ間のデータ期間が短いほど、障害の結果として失われるデータは少なくなります。バックアップの連続性とは、バックアップの数が増加し、少なくとも1週間は保存される必要があることを意味します。可能であれば、ストリーマーのような特別なデバイスにバックアップを書き込む必要がありますが、不可能な場合は、単に別のコンピューターにコピーします。バックアップコピーの履歴は、隠れた破損を発見し、ずっと前に発生して予期せず現れたエラーに対処するのに役立ちます。受け取ったバックアップをエラーなしで復元できるかどうかを確認する必要があります。これは1つの方法でのみ確認できます-テスト復元プロセスを通じてです。復元プロセスはバックアップの3倍の時間がかかり、大規模なデータベースでは毎日復元検証を実行することは困難です。なぜなら、ユーザーの作業を数時間中断する可能性があるからです(夜間の休憩では十分でない場合があります)。

大規模な組織では「マッチ(予備のPC)」をケチらず、こうした目的のために1台のコンピュータを残しておく方が良いでしょう。

この場合、サーバが24時間週7日の高負荷で稼働しなければならないのであれば、SHADOWメカニズムを使用してデータベースのスナップショットを取得し、その即時コピーからバックアップ操作を行うことができます。バックアッププロセスとデータベースの復元については、「バックアップと復元」の章で詳しく説明されています。バックアップを作成し、そこからデータベースを復元する際には、データベース内の全データの再作成が行われます。このプロセス(バックアップ/復元、またはb/r)は、ハードディスクの破損に関連するデータベース内のほとんどの非致命的なエラーの修正、データベース内の整合性問題の検出、データベースからのガベージ(古いバージョンやレコードの断片、不完全なトランザクション)のクリーンアップ、データベースサイズの大幅な削減に貢献します。

定期的なb/rは、InterBaseデータベースのセキュリティの保証です。データベースが稼働している場合、毎週b/rを実行することが推奨されます。実際のところ、バックアップ/復元なしで何年も集中的に使用されているInterBaseデータベースの例もあります。

それでも、安全側に立つためには、この手順を実行することが望ましいです。特に、簡単に自動化できるためです(「バックアップ」の章を参照)。

何らかの理由でバックアップ/復元を頻繁に実行できない場合は、データベースのチェックと復元にgfixツールを使用できます。gfixを使用すると、b/rなしで多くのエラーをチェックして削除できます。

2.8. コマンドラインツール gfix

コマンドラインツールgfixは、データベースのチェックと復元に使用されます。さらに、gfixはデータベース制御のさまざまな活動も実行できます:データベースのダイアレクトの変更、「読み取り専用」モードの設定と解除、特定のデータベースのキャッシュサイズの設定、およびいくつかの重要な機能(InterBase 6 Operations Guide [4.)で確認できます)。gfixはコマンドラインモードで実行され、次の構文を持ちます:

Gfix [ options] db name

Options - はgfixを実行するためのオプションのセットで、db nameはオプションのセットで定義された操作が実行されるデータベースの名前です。表3は、データベース修復に関連するgfixオプションを示しています:

オプション 説明
-f[ull] このオプションは-vと組み合わせて使用され、
レコードのすべての断片をチェックする時期であることを意味します
-i[gnore] このオプションは、検証またはデータベースクリーニング時に
gfixがチェックサムエラーを無視するようにします
-m[end] 損傷したレコードを利用不可としてマークし、
その結果、次のバックアップ/復元時に削除されます。
このオプションは、破損したデータベースをb/rに準備する際に使用されます。
-n[o_update] このオプションは-vと組み合わせて使用され、
破損を修正せずに読み取り専用でデータベースを検証します
-pas[sword] このオプションを使用すると、データベース接続時に
パスワードを設定できます。(InterBaseドキュメントの-pa[ssword]は誤りであり、
ショートカット「-pa」は機能しません。「-pas」を使用してください)
-user このオプションを使用すると、データベースに接続する
ユーザー名を設定できます
-v[alidate] エラーが検出される方法でデータベース検証を
事前設定するオプション
-m[ode] データベースの書き込みモードを設定するオプション -
読み取り専用または読み取り/書き込み。このパラメータは
2つの値 - read writeまたはread onlyを受け入れることができます。
-w[rite] {sync | async} データベースへの同期/非同期の強制書き込みモードを
オン/オフするオプション。sync - 同期書き込みをオンにする
(FW ON);async - 非同期書き込みをオンにする
(FW OFF);

表1:データベース復元のためのgfixツールオプション

gfixの使用例をいくつか示します:

gfix -w sync -user SYSDBA -pass masterkey firstbase.gdb

この例では、テストデータベースfirstbase.gdbに同期書き込みモード(FW ON)を設定しています。(もちろん、これは破損が発生する前に役立ちます)。そして以下は、破損が発生した後にデータベースをチェックするために使用すべき最初のコマンドです:

gfix -v -full -user SYSDBA -pass masterkey firstbase.gdb

この例では、テストデータベースのチェックを開始し(オプション-v)、レコードの断片もチェックする必要があることを示しています(オプション-full)。もちろん、チェックと復元プロセスにさまざまなオプションを設定するにはGUIを使用する方が便利ですが、ここではコマンドラインツールを使用したデータベースリカバリの機能を検討します。これらのツールはInterBaseに含まれており、InterBaseを実行しているすべてのOSで同じ動作をすることが確実です。それらが常に手元にあることは非常に重要です。

さらに、クライアントのコンピュータからデータベース管理を実行できる既存のツールは、そのためにServices APIを使用しますが、これはInterBaseサーバのClassicアーキテクチャではサポートされていません。つまり、サーバのアーキテクチャがSuperServerの場合にのみ、サードパーティ製品を使用できます。

2.9. 破損したデータベースの修復

データベースに何らかのエラーがあると仮定しましょう。まず、これらのエラーの存在を確認する必要があります。次に、これらのエラーを修正しようとする必要があります。以下の手順に従う必要があります。

InterBaseサーバがまだ稼働している場合は停止し、ファイルまたはデータベースファイルのコピーを作成する必要があります。すべての復元作業はデータベースのコピーに対してのみ実行する必要があります。選択した方法が不幸な結果につながる可能性があり、復元手順を(開始点から)再開しなければならなくなるためです。コピーを作成した後、データベース全体の検証(レコードの断片のチェック)を実行します。

そのために次のコマンドを実行する必要があります:

gfix -v - full corruptbase gdb -user SYSDBA - password

この場合、corruptbase.gdb - は損傷したデータベースのコピーです。コマンドは

データベースに構造的な破損がないかチェックし、未解決の問題のリストを提供します。そのようなエラーが検出された場合、損傷したデータを削除し、次のコマンドを使用してバックアップ/復元の準備をする必要があります:

gfix -mend -user SYSDBA -password your_masterkey corruptbase gdb

コマンドを実行した後、データベースにエラーが残っていないかチェックする必要があります。そのためにgfixをオプション-v -fullで実行し、プロセスが完了したら、データベースのバックアップを実行する必要があります:

gbak -b -v -ig -user SYSDBA -password corruptbase.gdb corruptbase.gbk

このコマンドはデータベースのバックアップを実行し(オプション-bがそれを示しています)、バックアッププロセスの実行に関する詳細情報を取得します(オプション-v)。チェックサムに関するエラーは無視されます(オプション-ig)。コマンドラインツールgbakのオプションについてさらに詳しく知りたい場合は、「バックアップと復元」の章で確認できます。バックアップに何らかのエラーがある場合は、別の構成で開始する必要があります:

gbak -b -v -ig -g -user SYSDBA -password corruptbase.gdb

corruptbase.gbk

ここで、オプション-gはバックアップ中のガベージコレクションをオフにします。これがバックアップの問題を解決するのに役立つことがよくあります。

また、その前にデータベースを読み取り専用モードに設定すれば、データベースのバックアップを作成できる可能性があります。このモードはデータベースへの変更の書き込みを防ぎ、損傷したデータベースのバックアップを実行するのに役立つことがあります。データベースを読み取り専用モードに設定するには、次のコマンドを使用する必要があります:gfix -m read _only

-user SYSDBA -password masterkey Disk:\Path\file.gdb

その後、上記のパラメータを使用してデータベースのバックアップを再度実行してみる必要があります。

バックアップが正常に完了した場合、バックアップコピーからデータベースを復元する必要があります。

次のコマンドを使用する必要があります:

gbak -c -user SYSDBA -password masterkey Disk:\Path\backup.gbk

Disk:\Path\newbase,gdb

データベースを復元する際、特にインデックスを作成するときに問題が発生する可能性があります。

この場合、オプション-inactiveと-one_at_a_timeを復元コマンドに追加する必要があります。これらのオプションは、データベースバックアップから作成する際にインデックスを非アクティブ化し、各テーブルのデータ確認をコミットします。

2.10. 破損したデータベースからデータを抽出する方法

上記の操作がデータベースのリカバリにつながらない可能性があります。

これは、データベースが深刻な損傷を受けているか、単一の全体として復元できないか、あるいは復旧に多大な労力が必要であることを意味します。例えば、システムメタデータの変更を実行したり、文書化されていない関数を使用したりする必要があるかもしれません。これは非常に困難で長期間にわたる報われない作業であり、成功の可能性は疑わしいものです。可能であれば、それを避けて他の方法を使用するようにしてください。損傷したデータベースが開き、一部のデータの読み取りおよび変更操作を実行できる場合は、その可能性を利用して、データを新しいベースにコピーして保存し、古いものとは永久に「お別れ」するべきです。

したがって、古いデータベースからデータを転送する前に、宛先データベースを作成する必要があります。データベースが長期間変更されていない場合は、古いバックアップを使用できます。そこからメタデータを抽出して、宛先データベースを作成できます。このメタデータに基づいてデータの宛先を作成し、データのコピーを開始する必要があります。主なタスクは、損傷したデータベースからデータを抽出することです。その後、データを新しいベースに配置する必要がありますが、データベース構造を記憶から復元しなければならない場合でも、それはそれほど難しくありません。テーブルからデータを抽出する際には、次の操作アルゴリズムを使用する必要があります:

  • まず、テーブルNからSELECT*を実行してみてください。正常に実行された場合は、取得したデータを外部ソースに保存できます。テーブルにBLOBフィールドが含まれていない限り、データをスクリプトに保存することをお勧めします(ほとんどすべてのGUIがこの機能を提供しています)。テーブルにBLOBフィールドがある場合は、それらのデータを仲介役となるクライアントプログラムによって別のデータベースに保存する必要があります。データ復旧の目的のために、この簡単なプログラムを特別に作成する必要があるかもしれません。
  • すべてのデータを取得できなかった場合は、すべてのインデックスを削除して再試行する必要があります。実際には、復元の最初からすべてのテーブルからインデックスを削除できます。それらはもう必要ないからです。もちろん、破損したものと同じメタデータの構造がない場合は、損傷したデータベースソースに対して行っているすべての操作のプロトコルを記録する必要があります。
  • インデックスを削除した後もテーブルからすべてのデータを読み取れない場合は、主キーによる範囲クエリを試すことができます。これは、データの特定の範囲を選択することを意味します。例えば:

SELECT * FROM table N WHERE field_PK >=0 and field_PK <=10000

ここでField_PKは主キーです。InterBaseはページデータ編成を採用しているため、値の範囲クエリはシャーマニズムのように見えるかもしれませんが、かなり効果的です。それでも機能するのは、クエリから損傷したページのデータを除外し、幸運にも他のページを読み取ることができるからです。SQLにはレコードの格納順序が定義されていないという私たちのテーゼを思い出すことができます。実際には、順序付けされていないクエリが再起動時に同じ順序でレコードを返すことを誰も保証しませんが、それでも物理レコードはデータベース内で定義された内部順序で格納されています。サーバーがSQL標準を遵守するためだけにレコードを混ぜることはないのは明らかです。この内部順序を利用して、損傷したデータベースからデータを抽出することができます(データページとその相関関係について詳しく知りたい場合は、「InterBaseデータベースの構造」の章を参照してください)。

経験豊富なロシアのInterBase開発者の一人であるVitaliy Barminは、この方法で復元不可能なデータベース(多数の損傷ページがあった)から最大98%の情報を復元できたと報告しました。したがって、損傷したデータベースからのデータは、新しいデータベースまたはSQLスクリプトなどの外部ソースに移動する必要があります。データをコピーする際には、損傷したデータベースのジェネレータ値に注意してください(新しいデータベースで適切な作業を再開するために保存する必要があります)。メタデータの完全なコピーがない場合は、ストアドプロシージャ、トリガー、制約のテキスト、およびインデックスの定義を抽出する必要があります。

2.11. 絶望的なデータベースの復元

一般的に、データベースの復元は非常に面倒で困難な場合があるため、損傷したデータを復元するよりもデータベースのバックアップコピーを作成する方が良いです。何が起こっても、最も困難な状況でも解決策が見つかるため、絶望してはいけません。ここで2つのケースを検討します。

最初のケース(古典的な問題)。NOT NULL制約のある列にNULL値があるために復元できないバックアップ(復元プロセスが作業ファイルに対して実行された)。作業ファイルは消去され、復元プロセスはエラーのために中断されました。そして軽率な行動の結果、バックアップコピーの代わりに大量の役に立たないデータ(復元できない)が残りました。しかし解決策は見つかりました。プログラマーは、どのテーブルのどの列にNOT NULL制約があったかを思い出すことができました。バックアップファイルを16進エディタにロードしました。そして、この列の定義に対応するバイトの組み合わせを検索して見つけました。数多くの実験の結果、NOT NULL制約は列名の近くのどこかに1を追加することが判明しました。HEXエディタでこの「1」を「0」に修正し、バックアップコピーが復元されました。その事件の後、プログラマーはバックアッププロセスと復元の実行方法を完全に記憶しました。

2番目のケース。状況は壊滅的でした。ディスク容量不足のために拡張フェーズでデータベースが破損しました。データベースサイズを増やす際、サーバーは一連の非常に重要なページ(例えば、トランザクションインベントリページとページインベントリページ、RDB$Pagesリレーションの追加ページ)を作成し、それらをデータベースの末尾に書き込みます。その結果、データベースは管理ツールでもGBAKユーティリティでも開けませんでした。データベースに接続しようとすると、エラーメッセージ(「Unexpected end of file」)が表示されました。

gfixユーティリティを実行すると奇妙なことが起こりました:プログラムは無限ループで動作していました。gfixが動作している間、サーバーは高速(毎秒約100 Kb)でログ(InterBaseログファイル)にエラーを書き込んでいました。その結果、ログファイルはすべての空きディスク容量を非常に迅速に埋め尽くしました。このログをタイマーで消去するプログラムを作成する必要さえありました。このプロセスは長時間続きました - gfixは16時間以上も結果なしで動作していました。ログは次のようなエラーで埋め尽くされました:「Page XXX doubly allocated」。InterBaseのソース(val.#ファイル内)には、このエラーの短い説明があります。同じデータページが2回使用された場合にこのエラーが発生すると書かれています。このエラーが非常に重要なページの破損の結果であることは明らかです。

その結果、数日間の不運な実験の後、標準的な方法でデータを復元する試みは断念されました。そのため、損傷したデータベースに保存されているデータの低レベル分析を使用する必要がありました。

East View Publications Incの情報技術部門責任者であるAlexander Kozelskiyが、同様の復元不可能なデータベースから情報を抽出する方法のアイデアの作者です。

研究の結果得られた復元方法は、データベースがページ編成を持ち、各テーブルのデータがデータページごとに収集されているという事実に基づいていました。各データページには、そのページがデータを格納するテーブルの識別子が含まれています。いくつかの重要なテーブルからデータを復元することが特に重要でした。完全に機能する古いバックアップコピーから受け取った類似のテーブルからのデータがあり、それがパターンとして使用できました。パターンデータベースを16進ソースのエディタにロードし、関心のあるデータのパターンを検索しました。これらのデータは16進形式でバッファにコピーされ、その後、損傷したデータベースの残骸がエディタにロードされました。パターンに対応するバイトシーケンスが損傷したデータベースで見つかり、ページが分析されました(このシーケンスが見つかったページ)。

最初に開始ページを定義しましたが、データベースファイルのサイズがデータページサイズで割り切れるため、難しくありませんでした。現在のバイト数をページサイズ(8192バイト)で割り、結果を整数に丸めます(そして現在のページ番号を取得します)。次に、現在のページ番号にページサイズを掛けて、現在のページの開始に対応するバイト番号を取得しました。ヘッダーを分析して、ページのタイプ(データのあるページの場合、タイプは5です - InterBaseソースのセットからのods.hファイル、および「InterBaseデータベースの構造」の章を参照)と必要なテーブルの識別子を定義しました。

その後、データベース全体を解析し、必要なテーブルの全ページを1つのまとまりに収集してファイルに移動するプログラムが作成されました。

こうして最初に必要なデータを取得した後、選択したページの内容の解析を開始しました。InterBaseは領域節約のためにデータ圧縮を広く使用しています。例えば、「ABC」という文字列を含むVARCHARのような文字列は、次の値のシーケンスを格納します:文字列長(2バイト)、この場合は0003、次にシンボル自体、そしてチェックサムです。私たちは、16進形式から通常の表示形式にデータを変換する文字列およびその他のデータベース型のアナライザを作成する必要がありました。データベース内容を解析する「手動」方式を使用して、いくつかの重要なテーブルから最大80%の情報を抽出することに成功しました。その後、この経験に基づいて、本書の著者の一人であるOleg KulkovとAlexey Kovyazinが、InterBaseエンジンをバイパスしてデータベースに直接アクセスし、InterBaseデータベース内のデータを適切な方法で直接読み取り解釈できるユーティリティInterBase Surgeonを開発しました。

InterBase Surgeonを使用することで、破損の原因を特定し、InterBaseで開くことができず標準的な方法では復元できない完全に復旧不可能なデータベースの最大90%を復元することができました。

このプログラムは公式サイトwww.ib-aid.comからダウンロードできます。

3. 謝辞

このガイドの作成に協力してくれたすべての方々に感謝の意を表したいと思います:

Craig Stuntz、Alexander Nevsky、Konstantin Sipachev、Tatjana Sipacheva、そしてInterBaseおよびFirebirdコミュニティの親切で知識豊富なすべての方々。

この章についてご提案やご質問がありましたら、お気軽にメールでご連絡ください。

© 2002 Alexey Kovyazin, Serge Vostrikov.

Copyright © 2004 IBSurgeon Team. All rights reserved.