他のバージョンの文書10 | 9.6 | 9.5 | 9.4 | 9.3 | 9.2 | 9.1 | 9.0 | 8.4 | 8.3 | 8.2 | 8.1 | 8.0 | 7.4 | 7.3 | 7.2

F.2. amcheck

amcheckモジュールは、インデックスの構造の論理的な一貫性を検査する機能を提供します。 構造が適正であると見なされれば、エラーは報告されません。

この関数は、特定のインデックスの構造表現における様々な不変量を検査します。 インデックスの走査や、その他の重要な操作を担うアクセスメソッド関数の正しさは、これらの不変量を常に保つことに依存しています。 たとえば、ある関数は、とりわけすべてのB-Treeページの中の項目が論理的な順序になっていることを検査します。(たとえばtextのB-Treeインデックスでは、インデックスタプルは語句の照合順になっていなければなりません。) その特定の不変量が何らかの理由で保たれなければ、該当するページで二分探索が不正なインデックス走査をもたらし、SQL問い合わせに誤った答えを返すことになるでしょう。

検証は、インデックス走査自身で使われるのと同じ手続きを用いて行われます。 その手続きは、ユーザ定義演算子クラスのコードかもしれません。 たとえば、B-Treeインデックスの検査は、一つ以上のB-Treeサポート関数1ルーチンを用いる比較に依存しています。 演算子クラスサポート関数の詳細については37.14.3をご覧ください。

amcheck関数はスーパーユーザだけが使用できます。

F.2.1. 関数

bt_index_check(index regclass) returns void

bt_index_checkは対象となるB-Treeインデックスが、様々な不変量を維持していることをテストします。 例を示します。

test=# SELECT bt_index_check(c.oid), c.relname, c.relpages
FROM pg_index i
JOIN pg_opclass op ON i.indclass[0] = op.oid
JOIN pg_am am ON op.opcmethod = am.oid
JOIN pg_class c ON i.indexrelid = c.oid
JOIN pg_namespace n ON c.relnamespace = n.oid
WHERE am.amname = 'btree' AND n.nspname = 'pg_catalog'
-- Don't check temp tables, which may be from another session:
AND c.relpersistence != 't'
-- Function may throw an error when this is omitted:
AND i.indisready AND i.indisvalid
ORDER BY c.relpages DESC LIMIT 10;
 bt_index_check |             relname             | relpages 
----------------+---------------------------------+----------
                | pg_depend_reference_index       |       43
                | pg_depend_depender_index        |       40
                | pg_proc_proname_args_nsp_index  |       31
                | pg_description_o_c_o_index      |       21
                | pg_attribute_relid_attnam_index |       14
                | pg_proc_oid_index               |       10
                | pg_attribute_relid_attnum_index |        9
                | pg_amproc_fam_proc_index        |        5
                | pg_amop_opr_fam_index           |        5
                | pg_amop_fam_strat_index         |        5
(10 rows)

この例では、データベースtest中のすべてのカタログインデックスの検証を行うセッションを示しています。 検証したもっとも大きな10個のインデックスの詳細だけが表示されています。 エラーは出ていないので、テストしたすべてのインデックスは論理的に一貫していることがわかります。 当然のことながら、この問い合わせは、検証可能なデータベース中のすべてのインデックスに対してbt_index_checkを呼び出すように変更できます。

bt_index_checkは、ターゲットとなるインデックスと、それが所属するヒープリレーションに対してAccessShareLockを獲得します。 このロックモードは、単純なSELECT文がリレーションに対して獲得するのと同じものです。 bt_index_checkは、子/親関係に渡る不変量も、ターゲットのインデックスがヒープリレーションと一貫性があることも検査しません。 実行中のプロダクション環境で定期的、軽量なデータ破損検査が必要な場合、bt_index_checkを使うのが、検査の完全性と、アプリケーションの性能と稼働への影響を限定することとの間の最良のトレードオフになることがしばしばあります。

bt_index_parent_check(index regclass) returns void

bt_index_parent_checkは、ターゲットとなるB-Treeインデックスが様々な不変量を保っていることを検査します。 bt_index_parent_checkにより実施される検査は、bt_index_checkにより実施される検査のスーパーセットになっています。 bt_index_parent_checkは、bt_index_checkの更なる完璧版であると考えることができます。 つまり、bt_index_checkと違ってbt_index_parent_checkは、子/親関係に渡る不変量も検査します。 しかし、ターゲットのインデックスがヒープリレーションと一貫性があることは検査しません。 bt_index_parent_checkは、論理的な非一貫性やその他の問題を発見した場合、一般的な習慣に従ってエラーを報告します。

bt_index_parent_checkは、ターゲットインデックスにShareLockを獲得することを必要とします。 (ShareLockはヒープリレーションにも獲得されます。) このロックは、INSERTUPDATEDELETEが並行してデータ更新することを防ぎます。 また、このロックはVACUUMその他のユーティリティコマンドによって、背後にあるリレーションが同時に処理されることを防ぎます。 この関数は実行中のみロックを保持し、トランザクション全体に保持するのではないことに注意してください。

bt_index_parent_checkによる追加の検査では、様々な病的な事象を検出する可能性があります。 これらの現象は、チェック対象のインデックスが使用している間違った実装がされたB-Tree演算子クラスによるものや、もしかしたら関連するB-Treeインデックスアクセスメソッドのコード中のまだ見つかっていないバグによるものなのかもしれません。 bt_index_checkと違って、bt_index_parent_checkは、ホットスタンバイモードが有効な場合(すなわち、読み出し専用物理レプリカ)では使用できません。

F.2.2. amcheckを効果的に使う

amcheckは、データページチェックサムが検知できないような、様々なタイプの障害モードを効果的に検知できます。 以下のようなものがあります。

  • 演算子クラスの正しくない実装によって引き起こされる構造の非一貫性。

    オペレーティングシステムの照合順の比較ルールの変更による問題も含まれます。 textのような照合可能な型のデータの比較は、不変でなけれならず(B-Treeインデックスの走査のための、すべての比較が不変でなければならないのと同じことです)、それはオペレーティングシステムの照合順が決して変化してはいけないことを意味します。 まれであるとは言え、オペレーティングシステムの照合順ルールの更新は、これらの問題を引き起こします。 もっと普通に起こることとしては、マスターサーバとスタンバイサーバの照合順の違いが関与することです。 これは、使用されているオペレーティングシステムのメジャーバージョンに一貫性がないことによります。 そうした一貫性の欠如は一般的にスタンバイサーバでのみ起こるので、通常スタンバイサーバでのみ検出されます。

    そうした問題が起きても、影響を受けた照合順を使って順序付けられた個々のインデックスには影響ないかもしれません。 これは単純に、振る舞いにおける一貫性のなさにかかわらずインデックスされた値は同じ絶対的な順になるからです。 PostgreSQLがオペレーティングシステムのロケールと照合順をどう使用するかについての更なる詳細については、23.123.2をご覧ください。

  • 依拠するPostgreSQLのアクセスメソッド、あるいはソートコードにおける、潜在的なまだ見つかっていないバグによる破損。

    新規、あるいは提案中の PostgreSQLの機能が、論理的な非一貫性をもたらしかねないかどうか全般的にテストする際に、インデックスの構造的な一貫性の自動検証が役立ちます。 わかりやすいテスト戦略の一つは、関数標準の回帰テストを実行中に、amcheckを継続的に呼び出すことです。 テストの実行に関する詳細は、32.1をご覧ください。

  • 単にチェックサムが有効になっていないファイルシステムあるいはストレージサブシステムの障害。

    amcheckは、ブロックをアクセスする際に共有バッファがヒットした場合、検査時に共有メモリバッファ上に表現されたページを調査します。 結果として、amcheckは、検査時にファイルシステムから読み込んだデータを調査するとは限りません。 チェックサムが有効な場合、amcheckは壊れたブロックをバッファに読み込んだ際にチェックサム障害によるエラーを報告するかもしれません。

  • RAMおよび、広範囲に渡るメモリサブシステムとオペレーティングシステムの障害による破損。

    PostgreSQLは、訂正可能なメモリーエラーからは身を守らないので、業界標準のエラー訂正コード(ECC)、あるいはもっと優れた保護機構を使ったRAMを使って運用する前提となっています。 しかし、ECCメモリは典型的には単一ビットエラーに対してのみ耐性があり、メモリ破損に起因する障害に対して完全な保護を提供すると考えるべきではありません。

一般的に、amcheckは破損の存在を証明することはできますが、破損がないことを証明することはできません。

F.2.3. 破損の修復

amcheckが報告するエラーが関与する破損で、擬陽性のものはありません。 実用的には、amcheckはハードウェアの問題よりも、ソフトウェアバグを発見する可能性が高いです。 amcheckは、定義により発生してはならないはずの条件下で発生したエラーを報告するので、amcheckの報告するエラーを注意深く解析することがしばしば求められます。

amcheckが検出した問題を修復する一般的な方法はありません。 不変条件違反の根本的な原因の説明が求められます。 amcheckが検出した破損の診断には、pageinspectが有用な役割を担うかもしれません。 REINDEXは破損の修復には効果的ではないかもしれません。