[PostgreSQL]本当は怖いREINDEX

REINDEXをすると、そのIndexを使用するSELECT文はブロックされます。
そしてSELECT文はたいていIndexを使用します。
つまり、たいていのケースではREINDEXでSELECT文がブロックされます。
(ブロックされないのは、そのテーブルにアクセスが全く来ない場合とか、よっぽど特殊なケース)

公式マニュアルにはこのことがはっきり書かれていない(極めて紛らわしい書き方になっている)ので注意が必要です。
REINDEXはインデックスの元となるテーブルの書き込みをロックしますが、読み込みはロックしません。
また、処理中のインデックスに対する排他ロックを取得するので、そのインデックスを使用する読み込みはブロックされます。

http://www.postgresql.jp/document/8.4/html/sql-reindex.html
この説明の肝は最後の一文にあります。
たいていのSELECT文はインデックスを使用するので、「REINDEX中は読み込みブロックされる可能性が高い」と覚えておいた方が安全です。

ちなみに私は、「読み込みはロックしません」の意味を勘違いしてサービス稼働中にREINDEXしたら、サービス提供不能状態に陥ってしまいました。
公式MLの過去ログを見ると、私と同じように勘違いしてた人がいたようなので、一種のハマリポイントだと思われます。

どうすればよいか

サービス稼働中にIndexを再構築したい場合は、CREATE INDEX CONCURRENTLY というテクニックがあるのでこれを使いましょう。

ただしこのテクニックはPRIMARY KEY Indexに対しては使えません。
PRIMARY KEY Indexを再構築したい場合は、サービスを停止してREINDEXするか、PostgreSQL 9.1でALTER TABLE ADD PRIMARY KEY USING INDEXを使うしかありません。

まとめ


サービス稼働中にIndex再構築したい



それはPRIMARY KEY INDEXか?  No → 「CREATE INDEX CONCURRENTLY&リネーム&削除」手法を使う

YES↓

PostgreSQL 9.1以上か?  YES →「ALTER TABLE ADD PRIMARY KEY USING INDEX」手法を使う

No ↓

あきらめてサービス停止してREINDEX

カテゴリ: