「Cannot commit index」または部分的に復元された(一貫性のない)データベースからデータを取り出す方法
Alexey Kovyazin、最終更新日:2014年3月30日
破損を修正した後、復元ステップで「Cannot commit index」エラーが頻繁に発生します。Firebird 2.0以降ではこれは警告として表示され、データベースはオンラインになりません。Firebird 1.0〜1.5およびInterBaseでは、これは復元プロセスを停止させる非常に不快なエラーとして発生します(200GBのデータベース復元の最後にこのエラーを見るのは印象的です)。
「Cannot commit index..」エラーの原因は明白です。破損はデータベースの参照整合性に影響を与え、レコードが(サーバーの観点から)魔法のように消えてしまいます。
例えば、「Customers」テーブルと、外部キーで参照される関連テーブル「Orders」があるとします。破損がなければ、特定の顧客を参照するすべての注文を事前に削除せずに外部キーを違反したり、Customersからレコードを削除したりすることはできません。破損はデータベースファイルに低レベルで影響を与え、レコードを直接破壊します。外部キーレコードからマスターレコードへの未解決のリンクをサーバーが検出するのは、なんと驚くべきことでしょう。
ここで、復元プロセスについてのヒントを追加する必要があります。エンジンは非アクティブ化されたインデックスを持つすべてのテーブルを復元し(これによりテーブルへのレコードの投入が大幅に高速化されます)、その後、インデックスを1つずつアクティブ化(つまり構築)し始めます。つまり、復元プロセスがインデックス作成ステップを開始する時点で、すべてのデータはすでにデータベースに存在しており、「Cannot commit index..」エラーが表示されるのです。
さて、「Cannot commit index」エラーが表示されたときの最初の願いは、復元を完了させるために適切な外部キー制約を削除することです。問題は、不整合ではあるが正常に復元されたデータベースをどうするかです。削除された外部キーはビジネスロジックの重要な部分である可能性があります。
ここには2つのアプローチがあります。欠落したデータを再作成するか、不整合なデータを削除するかです。上記のCustomers-Ordersの例でそれが何を意味するか見てみましょう。
欠落データの再作成
不整合なOrdersに対して欠落したCustomersを再作成する必要があると判断したとします。この場合、失われたIDを特定する必要があります。通常、私は次のようなSQLクエリを使用します(適切なものに簡単に適用できると思います):
SELECT O.Customer_ID FROM ORDERS O WHERE NOT EXISTS ( SELECT C.Customer_ID FROM CUSTOMERS C WHERE O.Customer_ID=C.Customer_ID)
その後、欠落した主キーのリストを持つレコードを手動で挿入し、バックアップ/復元を再度実行できます。
整合性のあるデータのポンピング
不整合なレコードを失うことが許容できると考える場合、部分的に復元されたデータベースから空のデータベースへすべてのデータをポンピングし、不整合なレコードをスキップすることができます。以下のアプローチを使用します:
-
無料ツールIBDataPumpをダウンロードします http://www.clevercomponents.com/demo/datapump/IBPump.zip
-
次のコマンドを使用して、修復されたデータベース(IBFirstAID後)のバックアップからメタデータのみのデータベースを作成します
gbak -c -m -user SYSDBA -pass masterkey Disk:\Path\backup.fbk Disk:\Path\fresh.fdb
-
IBDataPumpを実行し、部分的に修復されたデータベースをソースとして、新しい空のデータベースをターゲットとして設定します
-
次のタブをクリックし、適切なボタンをクリックして、3番目のタブで「Pump」をクリックします。完了するまで待ちます(長いプロセスになる可能性があります。ターゲットデータベースのサイズの増加状況を確認することで、ある程度の目安を得られます)。
-
結果として、整合性のある外部キー関係を持つfresh.fdbデータベースが得られます。これは完全に問題ありません。
データベースに外部キーのループがある場合、IBDataPumpは警告を表示し、そのような制約のリストを提供します。ポンピングが利用可能になる前に、そのうちの1つ以上を削除する必要があります。
もちろん、ポンピングに特別なアプローチが必要なケースもあります。そのような状況に直面した場合は、サポートにお問い合わせください。