破損テーブル修正があるデータベースの修正

以下の説明内容は、SQL Anywhere Studio 8 でデータベースの破損問題を修正する場合に役立ちます。この手順は、旧バージョンのソフトウェアでは機能しない場合があります。

序文と警告:

必然的に、システムには障害が発生します。その障害には、ハードウェアの問題、ユーザによるエラー、自然災害、人為災害など、数多くの原因があります。理想を言えば、障害が発生したときに効果的なバックアップ/リカバリ方式を使用してリカバリするのが最善の方法です。このバックアップ/リカバリ方式は、組織のビジネス・ニーズに合わせて設計、テスト、実装を完全に行う必要があります。バックアップ/リカバリ手順の概要は、製品マニュアルに記載されています。また、Sybase Web サイトには、『What Backup, Recovery, and Disaster Recovery Mean to Your Adaptive Server Anywhere Databases』という Tech Doc もあります。この文書では、データベースのバックアップ/リカバリ方式の開発方法を説明しています。この文書は、http://www.ianywhere.com/whitepapers/backup_recovery_disaster_recovery.html にあります。場合によっては、バックアップからデータをリカバリできないことがあります。この問題は、無効なバックアップ、消失したバックアップ、破損したバックアップなど、さまざまな原因によって生じる可能性があります。その場合は、データベースをリカバリするのではなく、救出できることがあります。下記の方法を使用するか Sybase サポート・センタに問い合せれば、救出できるかもしれません。

救出手法ではなくリカバリ手法を使用することが、常に望ましいことに十分注意してください。救出手法は機能しないことがあり、救出手法が成功した場合であっても、重要なデータが失われる可能性があります。さらに、救出手法を使用して削除されたデータが外部キー関係でも使用される場合は、それらの関係を順番に再構築して、データベースの参照整合性を維持する必要があります。

データベースがレプリケーション環境に関与している場合は、下記の救出手順を使用しないでください。また、この救出手順は、SQL Anywhere Studio 8 以前のバージョンでは機能しない場合があります。

バックアップ:

以下の救出方法に進む前に、データベースとログ・ファイルの完全なバックアップが作成されていることを確認してください。

データベースを救出して、参照整合性の問題をすべてチェックしたら、すぐにデータを完全にバックアップして、より望ましいデータベース・リカバリではなくデータベース救出を強要するあらゆる問題に対処してください。もちろん、障害を発生させた問題についても、すべて対処する必要があります。

注意:以下の手順内で、asademo (Adaptive Server Anywhere (SQL Anywhere)) に用意されているサンプルのデータベース) やそのテーブルが出てきたら、各自のデータベースや破損テーブルに置き換えて考えてください。

破損テーブルがあるデータベースを修正するには、次の手順に従います。

1. Adaptive Server Anywhere (SQL Anywhere) 8.x を使用して、検証ユーティリティをデータベースに対して実行し、破損の原因を確認します。

2. 問題がインデックス処理に関連している場合は、問題のあるデータベースに対して dbunload -u コマンドを発行してみることができます。多くの場合は、この操作によって問題が修正されます。

3. データベースのアンロードと再ロードを実行しても問題が修正されず、そ
テーブル (たとえば、このアーティクル全体にわたって例で使用される product
内の破損によって生じている場合は、次のコマンドを試してください。

dbunload -u -c “uid=dba;pwd=sql;dbf=c:\Program Files\Sybase\SQL Anywhere
8\asademo.db” -e product -r c:\reload.sql c:\unload

このコマンドを発行すると、次のような結果になります。

C:\>dbunload -u -c “uid=dba;pwd=sql;dbf=c:\Program Files\Sybase\SQL Anywhere 8\asademo.db ” -e product -r c:\reload.sql c:\unload

Adaptive Server Anywhere Unload Utility Version 8.0.2.xxxx

Unloading “DBA”.”sales_order” into c:\unload\409.dat (relative to server)

Unloading “DBA”.”sales_order_items” into c:\unload\410.dat (relative to server)

Unloading “DBA”.”contact” into c:\unload\411.dat (relative to server)

Unloading “DBA”.”customer” into c:\unload\412.dat (relative to server)

Unloading “DBA”.”fin_code” into c:\unload\413.dat (relative to server)

Unloading “DBA”.”fin_data” into c:\unload\414.dat (relative to server)

Unloading “DBA”.”department” into c:\unload\416.dat (relative to server)

Unloading “DBA”.”employee” into c:\unload\417.dat (relative to server)

C:\>

dbunload コマンドの -e オプションで product が指定されたために、そのテーブルが省略されていることに注意してください。

4. 以下のコマンドを発行して、影響を受けるテーブル (この場合は、product テーブル) のスキーマだけを出力します。

dbunload -u -c “uid=dba;pwd=sql;dbf=c:\Program Files\Sybase\SQL Anywhere 8\asademo.db” -n -t product -r c:\reload_pr.sql c:\unload

5. Interactive SQL から、以下のコマンドを発行して、破損していないテーブルのデータをすべてファイルに出力します。このプロセスは、不要データや破損データに出会うまではデータを出力し続け、出会ったらクラッシュまたはアサートします。

SELECT * FROM product ORDER BY id >### c:\recover\filename1.txt

### は、テーブルに適したロー数を表します。

6. 同じコマンドを発行します。ただし、今回はテーブルの反対側から開始します。前回と同様に、このプロセスは不要データや破損データに出会うまではデータを出力し続け、出会ったらクラッシュまたはアサートします。

SELECT * FROM product ORDER BY id DESC >###
c:\recover\filename2.txt

7. 1 つのローまたは 1 つのロー・グループだけが破損している場合は、手順 8 に進むことができます。ただし、データベースでは破損したローの間に正常なデータのローが含まれている可能性があるため、多くの場合は手順 8 に進めません。したがって、テーブル内の破損ローの間に正常なデータのローが残っていないことを確認する必要があります。

正常なデータが残っていないことを確認するためには、さまざまな範囲を試して、どの部分で再びクラッシュまたはアサートするのかを調べる必要があります。

たとえば、1 ~ 500 のローを持つテーブルで、上記で扱った 2 つの SELECT 文を使用して 1 ~ 99 のローと 500 ~ 401 のローを取得したら、ダーティ・データまたは不要データが原因でロー 100 と 400 でそれぞれアサートしたと仮定します。これにより、ロー 101 ~ 399 が残ります。これらはすべて不要なローかもしれませんが、これらのローの一部または全部に正常なデータが含まれている可能性があります。

注意:「序文と警告」の項で説明したように、この救出方法がうまくいくという保証はありません。たとえば、オプティマイザがテーブルの逐次スキャンを実行した場合は、ORDER BY が指定されていても、常に同じポイントで失敗します。この問題が発生した場合は、ユーザによる予測を明示的に指定して、オプティマイザにインデックスを使用させることができます。ただし、これはオプティマイザがインデックスを使用することを保証するものではありません。先に説明したように、データをリカバリするための最善の方法は、適切なバックアップ/リカバリ方式を使用することです。

これらのローに正常なデータが含まれているかどうかを確認するには、まず次の文を発行します。
SELECT * FROM product
WHERE id >=101 ORDER BY id

「この文は、問題がある最初のローと同じかそれ以上のローをすべて選択して、次のダーティ・ローでクラッシュします。」

これがロー 400 の場合は、すべてが正常または有効なデータです。400 でない場合は、正常なデータをすべて見つけて後続の出力 .txt ファイルに再発行し終わるまで、この処理を行う必要があります。

SELECT * FROM product
WHERE id >=101 ORDER BY id >># c:\recover\filename3.txt

上記の SELECT 文がロー 250 でクラッシュすると仮定します。その場合は、次の SELECT 文を発行します。

SELECT * FROM product
WHERE id >=251 ORDER BY id >># c:\recover\filename3.txt

上記の SELECT 文がロー 350 でクラッシュする場合は、次の SELECT 文を発行します。

SELECT * FROM product
WHERE id >=351 >># c:\recover\filename4.txt

これはロー 400 でクラッシュします。ロー 400は、以前に SELECT 文がアサートした場所です。したがって、破損テーブルから正常なデータをすべて取り出したことになります。

8. 次のコマンドを使用して新しいデータベースを作成します。

dbinit c:\new.db

9. この新しいデータベースに Interactive SQL から接続し、手順 3 で作成した .sql ファイルを読み込みます。

READ c:\reload.sql

省略または除外されたテーブルに到達すると、エラー・メッセージが表示されます。[Continue] を選択します。そのテーブルが多数の外部キーによって参照された場合やビューで使用された場合は、別のエラーが報告されることがあります。

10. 次の文を発行して product テーブルを作成します。

READ c:\reload_pr.sql

11. 破損していないデータ (手順 5 で取り出したデータ) を新しい product テーブルに入力します。

LOAD TABLE product FROM c:\recover\filename1.txt FORMAT ascii

12. 次の文を発行して、手順 6 で取り出した product テーブルのデータを新しいデータベースに挿入します。

LOAD TABLE product FROM c:\recover\filename2.txt FORMAT ascii

13. 次の文を発行して、手順 7 で取り出した product テーブルのデータを新しいデータベースに挿入します。

LOAD TABLE product FROM c:\recover\filename3.txt FORMAT ascii
LOAD TABLE product FROM c:\recover\filename4.txt FORMAT ascii

13. 最後に、検証ユーティリティを実行して、データベースにエラーがないことを確認します。 たとえば、オフライン・データベースの場合は、次のコマンドを使用します。

dbvalid -c “uid=dba;pwd=sql;dbf=c:\asademo.db”

すでにサーバで実行されているデータベース (asademo) の場合は、次のコマンドを使用します。

dbvalid -c “uid=dba;pwd=sql;eng=asademo”

これらのコマンドを実行すると、次のメッセージが表示されます。
Adaptive Server Anywhere Validation Utility Version 8.0.2.xxxx
No errors reported
C:\>