PostgreSQLは、テーブルやインデックスなどは、それぞれ個別のファイルになっています。通常、これらのファイルを直接見ることはなく、あくまでもPostgreSQLのサーバに対してクエリを投げて、PostgreSQLのバックエンドプロセスがテーブルやインデックスなどのファイルを読み書きすることになります。
但し、何らかの異常(または単なる好奇心)が発生した場合、テーブルやインデックスのファイルそのものを直接見てみたくなることがあります。
そのような場合のために作成されているツールが "pg_filedump" と呼ばれるユーティリティです。
これは、PostgreSQLコアチームのTom Lane氏がひとりプロジェクトとして開発しているもので、インデックスやテーブルファイルを直接読み取って、その中身を人間に理解可能な形で表示してくれるツールです。pg_filedumpはpgFounderyで公開されています。
PgFoundry: pg_filedump: Project Info
http://pgfoundry.org/projects/pgfiledump/
今回は、このpg_filedumpユーティリティの使い方を紹介してみます。
■pg_filedumpのコンパイル
pg_filedumpをコンパイルするには、バージョン9.1まではPostegreSQLのソースコードが必要です(バージョン9.2以降は不要です)。具体的には src/backend/utils/hash/pg_crc.c というファイルの持つチェックサムテーブルを使うためです。
PostgreSQLをソースコードからコンパイルしていて、configureされた状態のソースツリーが手元にある場合には、tar.gzを解凍して、top_builddirを指定してMakefile.contribファイルを使ってmakeを実行すればコンパイルできます。
[snaga@devsv02 pgsql]$ tar zxf pg_filedump-9.1.0.tar.gz [snaga@devsv02 pgsql]$ cd pg_filedump-9.1.0 [snaga@devsv02 pg_filedump-9.1.0]$ make -f Makefile.contrib top_builddir=/home/snaga/pgsql/postgresql-9.1.6 gcc -O2 -Wall -Wmissing-prototypes -Wpointer-arith -Wdeclaration-after-statement -Wendif-labels -Wformat-security -fno-strict-aliasing -fwrapv -g -I. -I. -I/home/snaga/pgsql/postgresql-9.1.6/src/include -D_GNU_SOURCE -c -o pg_filedump.o pg_filedump.c (...snip...) gcc -O2 -Wall -Wmissing-prototypes -Wpointer-arith -Wdeclaration-after-statement -Wendif-labels -Wformat-security -fno-strict-aliasing -fwrapv -g pg_filedump.o pg_crc.o -L/home/snaga/pgsql/postgresql-9.1.6/src/port -Wl,-rpath,'/usr/local/pgsql91/lib',--enable-new-dtags -lpgport -lz -lreadline -ltermcap -lcrypt -ldl -lm -o pg_filedump [snaga@devsv02 pg_filedump-9.1.0]$ ls Makefile pg_crc.c@ pg_filedump* pg_filedump.h README.pg_filedump Makefile.contrib pg_crc.o pg_filedump.c pg_filedump.o [snaga@devsv02 pg_filedump-9.1.0]$但し、最近はRPMからインストールしていてソースコードが手元にない、というケースも多いと思います。その場合は、PostgreSQLのソースコードから src/backend/utils/hash/pg_crc.c を取り出してpg_filedumpのディレクトリに置き、Makefile.contribの以下の三行をコメントアウトした上で、前述したようにコンパイルします。
#EXTRA_CLEAN = pg_crc.c #pg_crc.c: $(top_srcdir)/src/backend/utils/hash/pg_crc.c # rm -f $@ && $(LN_S) $< .なお、8.3.21、8.4.14、9.0.10、9.1.6の各バージョンの pg_crc.c ファイルは以下にまとめておきましたので、必要に応じて利用してください。
pg_crc.tar.gz
■ダンプする対象ファイルを特定する
pg_filedumpコマンドの準備ができたら、ダンプする対象を探します。
今回は、特定のデータベース内にあるテーブルのインデックスファイルをダンプすることを考えてみます。
まず、oid2nameコマンドでデータベース名一覧を取得します。
[snaga@devsv02 pg_filedump-9.1.0]$ oid2name All databases: Oid Database Name Tablespace ---------------------------------------- 78684 datacmn pg_default 52284 foodmart pg_default 52258 pgbench pg_default 12699 postgres pg_default 52283 snaga pg_default 52513 sugarcrm pg_default 12691 template0 pg_default 1 template1 pg_default [snaga@devsv02 pg_filedump-9.1.0]$今回は "pgbench" データベースを対象にすることにします。
次に、pgbenchデータベース内のテーブルとインデックスの一覧を取得します。特定のデータベース内のテーブル一覧を取得するには "-d" オプションでデータベース名を指定し、インデックスも含めて表示するには "-i" オプションを指定します。
[snaga@devsv02 pg_filedump-9.1.0]$ oid2name -d pgbench -i From database "pgbench": Filenode Table Name --------------------------------- 52271 pgbench_accounts 52276 pgbench_accounts_pkey 52259 pgbench_branches 52272 pgbench_branches_pkey 52282 pgbench_history 52262 pgbench_tellers 52274 pgbench_tellers_pkey [snaga@devsv02 pg_filedump-9.1.0]$今回はこのうち、"pgbench_accounts_pkey" というpgbench_accountsテーブルのプライマリキーインデックスを対象にしてみます。
ここまでで、データベースpgbenchのOidは「52258」であり、pgbench_accounts_pkeyインデックスのFilenodeが「52276」であることが分かりました。
PostgreSQLでは、データベースクラスタ内のbaseディレクトリに「Oid」でディレクトリとして作成され、テーブルやインデックスのファイルはさらにその中に「Filenode」でファイルとして作成されていますので、この情報を使って実ファイルを探します。
bash-3.2$ ls -l /var/lib/pgsql/9.1/data/base/52258/52276 -rw------- 1 postgres postgres 224641024 Sep 13 00:22 /var/lib/pgsql/9.1/data/base/52258/52276 bash-3.2$というわけで、今回ダンプしたいpgbenchデータベース内のpgbench_accontsテーブルのプライマリキーインデックスpgbench_accounts_pkeyの実ファイルを特定できました。
■インデックスファイルをダンプする
それではこのファイルをダンプしてみましょう。おもむろにダンプしてみます。
bash-3.2$ pg_filedump /var/lib/pgsql/9.1/data/base/52258/52276 ******************************************************************* * PostgreSQL File/Block Formatted Dump Utility - Version 9.1.0 * * File: /var/lib/pgsql/9.1/data/base/52258/52276 * Options used: None * * Dump created on: Fri Nov 23 15:48:13 2012 ******************************************************************* Block 0 ********************************************************インデックスファイルのサイズにもよりますが、大量のデータが表示されます。----- Block Offset: 0x00000000 Offsets: Lower 48 (0x0030) Block: Size 8192 Version 4 Upper 8176 (0x1ff0) LSN: logid 143 recoff 0x8e4b0fb0 Special 8176 (0x1ff0) Items: 6 Free Space: 8128 TLI: 0x0001 Prune XID: 0x00000000 Flags: 0x0000 () Length (including item array): 48 BTree Meta Data: Magic (0x00053162) Version (2) Root: Block (290) Level (2) FastRoot: Block (290) Level (2) ----- BTree Index Section: Flags: 0x0008 (META) Blocks: Previous (0) Next (0) Level (0) CycleId (0) Block 1 ******************************************************** ----- Block Offset: 0x00002000 Offsets: Lower 1516 (0x05ec) Block: Size 8192 Version 4 Upper 2208 (0x08a0) LSN: logid 144 recoff 0x3f8f4508 Special 8176 (0x1ff0) Items: 373 Free Space: 692 TLI: 0x0001 Prune XID: 0x00000000 Flags: 0x0000 () Length (including item array): 1516 ------ Item 1 -- Length: 16 Offset: 2304 (0x0900) Flags: NORMAL Item 2 -- Length: 16 Offset: 8160 (0x1fe0) Flags: NORMAL Item 3 -- Length: 16 Offset: 8144 (0x1fd0) Flags: NORMAL Item 4 -- Length: 16 Offset: 8128 (0x1fc0) Flags: NORMAL (...snip...) Item 147 -- Length: 16 Offset: 5856 (0x16e0) Flags: NORMAL Item 148 -- Length: 16 Offset: 5840 (0x16d0) Flags: NORMAL Item 149 -- Length: 16 Offset: 5824 (0x16c0) Flags: NORMAL Item 150 -- Length: 16 Offset: 5808 (0x16b0) Flags: NORMAL ----- BTree Index Section: Flags: 0x0001 (LEAF) Blocks: Previous (27420) Next (0) Level (0) CycleId (0) *** End of File Encountered. Last Block Read: 27421 *** bash-3.2$
インデックスの各ブロックのヘッダに含まれる情報、インデックスエントリの格納情報(オフセット、サイズ)などを、上記の例ではブロック0からブロック27421までについてダンプしています。
■pg_filedumpのオプション
pg_filedumpにはさまざまなオプションがあります。
bash-3.2$ pg_filedump Version 9.1.0 (for PostgreSQL 9.1.x) Copyright (c) 2002-2010 Red Hat, Inc. Copyright (c) 2011, PostgreSQL Global Development Group Usage: pg_filedump [-abcdfhixy] [-R startblock [endblock]] [-S blocksize] file Display formatted contents of a PostgreSQL heap/index/control file Defaults are: relative addressing, range of the entire file, block size as listed on block 0 in the file The following options are valid for heap and index files: -a Display absolute addresses when formatting (Block header information is always block relative) -b Display binary block images within a range (Option will turn off all formatting options) -d Display formatted block content dump (Option will turn off all other formatting options) -f Display formatted block content dump along with interpretation -h Display this information -i Display interpreted item details -R Display specific block ranges within the file (Blocks are indexed from 0) [startblock]: block to start at [endblock]: block to end at A startblock without an endblock will format the single block -S Force block size to [blocksize] -x Force interpreted formatting of block items as index items -y Force interpreted formatting of block items as heap items The following options are valid for control files: -c Interpret the file listed as a control file -f Display formatted content dump along with interpretation -S Force block size to [blocksize] Report bugs to例えば、-Rオプションを指定することによって一部のブロックだけをダンプの対象とすることができますし、-iオプションを指定すると各アイテム(インデックスエントリやタプル)の中身まで含めてダンプすることができます。bash-3.2$
bash-3.2$ pg_filedump -R 100 100 -i /var/lib/pgsql/9.1/data/base/52258/52276 (...snip...) ------ Item 1 -- Length: 16 Offset: 2304 (0x0900) Flags: NORMAL Block Id: 594 linp Index: 1 Size: 16 Has Nulls: 0 Has Varwidths: 0 Item 2 -- Length: 16 Offset: 8160 (0x1fe0) Flags: NORMAL Block Id: 588 linp Index: 1 Size: 16 Has Nulls: 0 Has Varwidths: 0 Item 3 -- Length: 16 Offset: 8144 (0x1fd0) Flags: NORMAL Block Id: 588 linp Index: 2 Size: 16 Has Nulls: 0 Has Varwidths: 0 (...snip...)上記の例では、100番目のブロックについて、インデックスエントリの内容も含めてダンプしています。
例えば、ブロック内の最初のインデックスエントリ(Item 1)は、テーブルファイルのブロック594(Block Id: 594)の最初のタプル(linp index: 1)を指し示している、ということが分かるわけです。
上記はインデックスファイルの例でしたが、テーブルファイル(Filenode 52271はpgbench_accountsテーブル)に対して同じオプションを指定して実行すると、以下のような出力になります。
bash-3.2$ ./pg_filedump -R 100 100 -i /var/lib/pgsql/9.1/data/base/52258/52271 (...snip...) ------ Item 1 -- Length: 121 Offset: 8064 (0x1f80) Flags: NORMAL XMIN: 14517797 XMAX: 0 CID|XVAC: 1 Block Id: 100 linp Index: 1 Attributes: 4 Size: 24 infomask: 0x0902 (HASVARWIDTH|XMIN_COMMITTED|XMAX_INVALID) Item 2 -- Length: 121 Offset: 7936 (0x1f00) Flags: NORMAL XMIN: 14517797 XMAX: 0 CID|XVAC: 1 Block Id: 100 linp Index: 2 Attributes: 4 Size: 24 infomask: 0x0902 (HASVARWIDTH|XMIN_COMMITTED|XMAX_INVALID) (...snip...)これは、各タプル(レコード)のヘッダ情報をダンプしたものです。
このようにpg_filedumpを使うことによって、インデックスファイルやテーブルファイルの物理的な内容を直接的に確認することができます。
■まとめ
今日は「pg_filedump」というPostgreSQLのインデックスファイルやテーブルファイルを、直接ダンプするユーティリティの使い方を紹介しました。
普通に使っている時にはあまり気にしないと思いますが、インデックスやテーブルファイルの詳細を人間が読める形式で表示できるため、トラブルシューティングや動作を解析したい場合などに重宝することがあるツールです。
ぜひ、頭の片隅に置いておいて、機会があれば使ってみていただければと思います。
ではでは。
0 件のコメント:
コメントを投稿