はじめに
PostgreSQL Advent Calendarに乗り遅れた!(挨拶)
PostgreSQLのデータファイルをバイナリエディタで確認するユーティリティを使ってみたので、そのメモです。
ソースや使い方は以下から。
https://github.com/petergeoghegan/pg_hexedit
インストールの仕方は上記サイトに載ってるので割愛。
データが壊れるかもしれないのでローカルの開発環境で利用してね、ってことらしいです。
検証
早速テスト用テーブルを作って試してみます。
create table hoge (col1 varchar, col2 varchar);
insert into hoge values ('00001','AAAAA');
実行はrelation_hexedit シェルの引数にテーブル名を指定する形です。
matsu@matsu-TM1613:~/pg_hexedit$ ./relation_hexedit hoge
導入が成功していると以下のようなウィンドウが起動します。
INSERTしたデータはファイルの末尾の方にあります。
00000やAAAAAがウィンドウの右側に表示されているのがわかります。
PostgreSQLはブロックの後ろの方からデータを書いていくので、先程INSERTしたデータはこの時点でファイルの末尾にあります。
ちなみにPostgreSQLのファイル構造についてはsrc/include/storage/bufpage.h のコメントに説明があります。
22 /*
23 * A postgres disk page is an abstraction layered on top of a postgres
24 * disk block (which is simply a unit of i/o, see block.h).
25 *
26 * specifically, while a disk block can be unformatted, a postgres
27 * disk page is always a slotted page of the form:
28 *
29 * +----------------+---------------------------------+
30 * | PageHeaderData | linp1 linp2 linp3 ... |
31 * +-----------+----+---------------------------------+
32 * | ... linpN | |
33 * +-----------+--------------------------------------+
34 * | ^ pd_lower |
35 * | |
36 * | v pd_upper |
37 * +-------------+------------------------------------+
38 * | | tupleN ... |
39 * +-------------+------------------+-----------------+
40 * | ... tuple3 tuple2 tuple1 | "special space" |
41 * +--------------------------------+-----------------+
42 * ^ pd_special
43 *
1枚めの画像ではPageHeaderDataとlinp1、2枚めの画像ではtuple1に相当する部分が表示されてます。
末尾のspecial spaceの領域は無いようです。(ヘッダのpd_specialで指してるアドレスが8192)
もうちょっとデータをINSERTして、UPDATEしてみます。
insert into hoge values ('00002','BBBBB');
insert into hoge values ('00003','CCCCC');
update hoge set col2='CCCCC' where col1='00002';
後ろの方からレコードが追加されていることがわかります。
また、UPDATEしたデータに着目すると、UPDATE前のレコード(00002とBBBBBのレコード)が8137、UPDATE後のレコード(00002とCCCCCのレコード)が8056のあたりにあることがわかります。PostgreSQLは追記型アーキテクチャである、ということが目視できて少し感動です。
UPDATEの次はvacuumしてみますか
vacuum hoge;
8032〜8071のデータはデータが上書きされていませんが、ツール上色付けされてないです。おそらくここが開放された領域と考えられます。この状態で、INSERTするとこの領域が上書きされることが期待されます。
insert into hoge values ('00004','DDDDD');
期待通り、開放された領域が別レコードで上書きされています。
まとめ
というわけで、このpg_hexeditを使うとUPDATEやVACUUM実行時のファイル構造が簡単に見られて良さげでした。
本当はツール上で対象データのところにマウスポインタを置くと、データ型とかが表示されるのでもっとわかりやすいです(単にスクショとるときの都合でここでは表示できてないです。。)
↓のページの内容やソースコードと照らし合わせながら確認すると理解が進みそうなので、今後チャレンジしていきたいところです。
http://pgsqldeepdive.blogspot.jp/2012/12/postgresql_16.html