13. clustered のコードを読む5 - PostgreSQL のソースコードを読む
少し脱線してロックについて見て回る。
ロックが獲得されるのは
- ユーザーが明示的にロックする
- LOCK コマンド
- Query や transaction に付随して DBMS が裏でロックする
の2つある。
ロックの種類とその意味は以下。
http://www.postgresql.jp/document/pg721doc/reference/sql-lock.html
- ACCESS SHARE
- ROW SHARE
- ROW EXCLUSIVE
- SHARE UPDATE EXCLUSIVE
- SHARE
- SHARE ROW EXCLUSIVE
- EXCLUSIVE
- ACCESS EXCLUSIVE
これはコード上は lock.h で定義されている。
#define AccessShareLock 1 /* SELECT */ #define RowShareLock 2 /* SELECT FOR UPDATE/FOR SHARE */ #define RowExclusiveLock 3 /* INSERT, UPDATE, DELETE */ #define ShareUpdateExclusiveLock 4 /* VACUUM (non-FULL),ANALYZE, CREATE * INDEX CONCURRENTLY */ #define ShareLock 5 /* CREATE INDEX (WITHOUT CONCURRENTLY) */ #define ShareRowExclusiveLock 6 /* like EXCLUSIVE MODE, but allows ROW * SHARE */ #define ExclusiveLock 7 /* blocks ROW SHARE/SELECT...FOR * UPDATE */ #define AccessExclusiveLock 8 /* ALTER TABLE, DROP TABLE, VACUUM * FULL, and unqualified LOCK TABLE */
コード上でロックを獲得するには heap_openrv や heap_open の第2引数に lock mode を渡せば良い。
cluster コマンドにおけるロック
cluster コマンドでは、relation と index のどちらとも AccessExclusiveLock が使われている。
- ALTER TABLE
- DROP TABLE
- VACUUM FULL
などでも使われているロックで、ロックを獲得したプロセス以外はテーブルに触れなくなる。
cluster コマンドでこのロックが使われているのは、恐らくテーブルのコピーが行われるから。テーブルコピー中に、コピー元が ALTER TABLE, DROP TABLE, VACUUM FULL されると困るのだろう。
逆に言えば、上記コマンドを CLUSTER 中に発行しないならば、ExclusiveLock で済むはずなので、CLUSTER 化中に select できるんだが。
上記の方法で unsafe な CLUSTER コマンドを実装するのはどうなのだろうか。
todo
- MemoryContext
- cluster にもどり heap の copy など