PostgreSQL

[PostgreSQL] pg_hexeditを使ってファイル構造を確認する

はじめに

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

導入が成功していると以下のようなウィンドウが起動します。

wxHexEditor 0.24 Beta Development for Linux_001.png

INSERTしたデータはファイルの末尾の方にあります。

wxHexEditor 0.24 Beta Development for Linux_002.png

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';

wxHexEditor 0.24 Beta Development for Linux_003.png

後ろの方からレコードが追加されていることがわかります。
また、UPDATEしたデータに着目すると、UPDATE前のレコード(00002とBBBBBのレコード)が8137、UPDATE後のレコード(00002とCCCCCのレコード)が8056のあたりにあることがわかります。PostgreSQLは追記型アーキテクチャである、ということが目視できて少し感動です。
UPDATEの次はvacuumしてみますか

vacuum hoge;

wxHexEditor 0.24 Beta Development for Linux_005.png

8032〜8071のデータはデータが上書きされていませんが、ツール上色付けされてないです。おそらくここが開放された領域と考えられます。この状態で、INSERTするとこの領域が上書きされることが期待されます。

insert into hoge values ('00004','DDDDD');

wxHexEditor 0.24 Beta Development for Linux_007.png

期待通り、開放された領域が別レコードで上書きされています。

まとめ

というわけで、このpg_hexeditを使うとUPDATEやVACUUM実行時のファイル構造が簡単に見られて良さげでした。
本当はツール上で対象データのところにマウスポインタを置くと、データ型とかが表示されるのでもっとわかりやすいです(単にスクショとるときの都合でここでは表示できてないです。。)

↓のページの内容やソースコードと照らし合わせながら確認すると理解が進みそうなので、今後チャレンジしていきたいところです。
http://pgsqldeepdive.blogspot.jp/2012/12/postgresql_16.html