20140531 JPUGしくみ+アプリケーション分科会 勉強会資料

32
PostgreSQLのデータ構造と内容を知る - 便利な外部ツールの一部紹介 - JPUGしくみ + アプリーケーション分科会 勉強会 2014.5.31 笠原辰仁 @kasa_zip

description

 

Transcript of 20140531 JPUGしくみ+アプリケーション分科会 勉強会資料

Page 1: 20140531 JPUGしくみ+アプリケーション分科会 勉強会資料

PostgreSQLのデータ構造と内容を知る- 便利な外部ツールの一部紹介 -

JPUGしくみ + アプリーケーション分科会 勉強会2014.5.31

笠原辰仁@kasa_zip

Page 2: 20140531 JPUGしくみ+アプリケーション分科会 勉強会資料

アジェンダ● はじめに● PostgreSQLを構成するデータ● 構造、状況を把握するツール群● 各種ツールの使い方と代表的な利用例

Page 3: 20140531 JPUGしくみ+アプリケーション分科会 勉強会資料

はじめに● 本日は、PostgreSQLのデータ構造やその内容を

知るために有用なツールとその簡単な使い方を紹介します

● 最近はプレ勉強会や永安氏の公開しているPostgreSQL internals など、PostgreSQLの内部を深く知るための手段や機会が増えてきました– http://www.postgresqlinternals.org/index.php/

● 内部構造を知る上で、理解の手助けになれば・・● また、最近はPostgreSQLの利用シーンも増えて

おり、データ破損などの調査も必要になるケースが増えているので・・・

Page 4: 20140531 JPUGしくみ+アプリケーション分科会 勉強会資料

PostgreSQLを構成するデータ● 代表的なデータ

名称 説明 格納先テーブル テーブルデータ。デフォルトでは8kBブ

ロックの固まりで、1GBファイル1単位に分割されている。

$PGDATA/base$PGDATA/global<テーブルスペース>/<識別子>/

インデックス インデックスデータ。基本的な構成はテーブルデータと同じ。

$PGDATA/base$PGDATA/global<テーブルスペース>/<識別子>/

FSM(Free Space Map) テーブル内に存在する空き領域の場所と大まかな空きサイズをマッピングしたファイル。

テーブルと同じ

VM(Visibility Map) テーブルのブロック単位での可視マップファイル。1ブロック1bit1で管理。不要レコードがなければ1

テーブルと同じ

一時ファイル ディスクソートやハッシュ処理時に生成される一時ファイル。処理終了時に削除される。

$PGDATA/base/pgsql_tmp

Page 5: 20140531 JPUGしくみ+アプリケーション分科会 勉強会資料

PostgreSQLを構成するデータ● 代表的なデータ

名称 説明 格納先トランザクションログ DBに変更を行った処理のログ $PGDATA/pg_xlog/コミットログ 各トランザクションのコミット状況

を記録しているログ$PGDATA/pg_clog/

制御ファイル XIDなどインスタンスの重要なメタデータを記録しているファイル(pg_control 512byte 固定)

$PGDATA/global/

稼働統計情報ファイル 内部で取得されている稼働統計情報のファイル。

$PGDATA/pg_stat/$PGDATA/pg_stat_tmp/

Multixactファイル(名前適当)

共有ロック状態を記録しているファイル。

$PGDATA/pg_multixact/

Serialファイル(名前適当)

SSIトランザクションのコミット状況を記録しているファイル。

$PGDATA/pg_serial/

サブトランザクションファイル

SAVEPOINTを使用したサブトランザクションの状況を記録しているファイル。

$PGDATA/subtrans/

スナップショットファイル

pg_export_snapshot()でエクスポートしたスナップショット情報。

$PGDATA/pg_snapshots/

Page 6: 20140531 JPUGしくみ+アプリケーション分科会 勉強会資料

PostgreSQLを構成するデータ● 代表的なデータ

名称 説明 格納先PreparedTransactionファイル

2フェーズコミット用のプリペアトランザクションの状態を記録てしているファイル。

$PGDATA/pg_twophase/

Filenodeマップファイル pg_classを経由しないアクセスが実施されるシステムカタログのOIDと物理ファイルのマップファイル(pg_filenode.map 512byte 固定)

$PGDATA/global/$PGDATA/base/

relationキャッシュファイル

各種リレーションのキャッシュファイル(backendの初期化高速用)(pg_internal.init)

$PGDATA/global/$PGDATA/base/

設定ファイル PostgreSQLの設定ファイル(postgresql.conf)

$PGDATA

アクセス制御ファイル PostgreSQLのホストベースのアクセス制御ファイル(pg_hba.conf)

$PGDATA

起動コマンドファイル PostgreSQLを起動した際のコマンドを記録したファイル(postmaster.opts)

$PGDATA

Page 7: 20140531 JPUGしくみ+アプリケーション分科会 勉強会資料

便利なツール群(主に開発)● データ構造や属性の確認に便利

名称 説明 解析対象 PostgreSQL起動

pg_filedump(外部ツール)

テーブルやインデックスデータの物理イメージをダンプして可視化するツール。pagseinspectがあればほぼ不要・・

テーブルインデックス

不要

pg_xlogdump(9.3からcontrib)

トランザクションログの内容を可視化するツール。

トランザクションログ

不要

pageinspect(8.3からcontrib)

テーブルやインデックス、FSMのメタ情報(主にヘッダ情報)を可視化するツール

テーブルインデックスFSM

必要

Page 8: 20140531 JPUGしくみ+アプリケーション分科会 勉強会資料

便利なツール群(主に検証・運用)● データの統計的な俯瞰、確認に便利

名称 説明 解析対象 PostgreSQL起動

pgstattuplet(contrib)

テーブルやインデックスの不要領域や断片化状況を数値化するツール。

テーブルインデックス

必要

pg_buffercache(contrib)

テーブルやインデックスがPostgreSQLの共有バッファにどれだけ格納されているかを数値化するツール。

テーブルインデックス

必要

pg_fincore(外部ツール)

テーブルやインデックスがOSのファイルキャッシュにどれだけ格納されているかを数値化するツール。

テーブルインデックス

必要

pg_freespacemap(contirb)

FSMにマッピングされている空き領域状況を数値化するツール。

FSM 必要

Page 9: 20140531 JPUGしくみ+アプリケーション分科会 勉強会資料

テーブル/インデックスのページ構造を調べる

* +-----------------------+---------------------------------+ * | PageHeaderData | linp1 linp2 linp3 ... | * +---------------+------+---------------------------------+ * | ... linpN | | * +---------------+-----------------------------------------+ * | ^ pd_lower | * | | * | v pd_upper | * +-------------+-------------------------------------------+ * | | tupleN ... | * +-------------+-----------------------+-------------------+ * | ... tuple3 tuple2 tuple1 | "special space"| * +--------------------------------------+-------------------+ * ^ pd_special

Page 10: 20140531 JPUGしくみ+アプリケーション分科会 勉強会資料

pageinspect● contribに付属しているツール● contribモジュールのmakeないしはRPMパッ

ケージ等で導入– pageinspectを実施したいDBでCREATE

EXTENSION● テーブル、インデックス名をインップットし、

ページヘッダやタプルヘッダのメタ情報の調査に有用

● 手軽に使えておすすめ

Page 11: 20140531 JPUGしくみ+アプリケーション分科会 勉強会資料

pageinspectの出力例(テーブル)(詳細は include/storage/bufpage.h)

postgres=# SELECT * FROM page_header(get_raw_page('test', 0));-[ RECORD 1 ]--------lsn | 0/1F88F90checksum | 0flags | 0lower | 44upper | 8032special | 8192pagesize | 8192version | 4prune_xid | 1094

Flagsはページ単位の状態を表すヒント。PD_PAGE_FULL ,

PD_ALL_VISIBLEなどVersionはページレイアウトの

* Page layout version number 0 is for pre-7.3

* Releases 7.3 and 7.4 use 1. * Release 8.0 uses 2 * Release 8.1 uses 3 * Release 8.3 uses 4

Page 12: 20140531 JPUGしくみ+アプリケーション分科会 勉強会資料

pageinspectの出力例(テーブル)(詳細は include/access/htup_details.h)

postgres=# SELECT * FROM heap_page_items(get_raw_page('test', 0));-[ RECORD 1 ]---------lp | 1lp_off | 8160lp_flags | 1lp_len | 28t_xmin | 1097t_xmax | 0t_field3 | 0t_ctid | (0,1)t_infomask2 | 3t_infomask | 2049t_hoff | 24t_bits | 10000000t_oid |

lp_flags はラインポインタの状態0:未使用、1:通常、

2:REDIRECT, 3: DEADt_infomaskがタプルの状態を細かく管理している重要なフラグ部位。左記は10進数

t_bitsはNULL値の管理

Page 13: 20140531 JPUGしくみ+アプリケーション分科会 勉強会資料

pageinspectの出力例(インデックス)(詳細は include/access/nbtree.h)

postgres=# SELECT * FROM bt_metap('test_pkey');-[ RECORD 1 ]-----magic | 340322version | 2root | 1level | 0fastroot | 1fastlevel | 0

Page 14: 20140531 JPUGしくみ+アプリケーション分科会 勉強会資料

pageinspectの出力例(インデックス)(詳細は include/access/nbtree.h)

postgres=# SELECT * FROM bt_page_stats('test_pkey', 1);-[ RECORD 1 ]-+-----blkno | 1type | llive_items | 3dead_items | 0avg_item_size | 16page_size | 8192free_size | 8088btpo_prev | 0btpo_next | 0btpo | 0btpo_flags | 3

btpo_* はspecial領域にあるBtree専用の情報

Page 15: 20140531 JPUGしくみ+アプリケーション分科会 勉強会資料

pageinspectの出力例(インデックス)postgres=# SELECT * FROM bt_page_items('test_pkey', 1);-[ RECORD 1 ]-----------------------Itemoffset | 1ctid | (0,1)itemlen | 16nulls | fvars | fdata | 01 00 00 00 00 00 00 00

-[ RECORD 2 ]-----------------------itemoffset | 2ctid | (0,2)itemlen | 16nulls | fvars | fdata | 02 00 00 00 00 00 00 00

ctidはテーブルのラインポインタ

data は実際のキー値

Page 16: 20140531 JPUGしくみ+アプリケーション分科会 勉強会資料

pageinspectの出力例(インデックス)postgres=# SELECT * FROM bt_page_items('test2_idx', 1);-[ RECORD 1 ]-----------------------Itemoffset | 1ctid | (0,1)itemlen | 16nulls | fvars | tdata | 01 00 00 00 09 41 41 41

-[ RECORD 2 ]-----------------------itemoffset | 2ctid | (0,2)itemlen | 16nulls | fvars | tdata | 02 00 00 00 09 42 42 42

マルチカラムインデックスはこんな感じに見える

1, 'AAA'2, 'BBB'

の16進数表記(文字の前の09はヘッダ含むサイズ)

9 >> 1 = 4 = (1 + 3)

Page 17: 20140531 JPUGしくみ+アプリケーション分科会 勉強会資料

pg_filedump● Pgfoundryで公開されている外部ツール● contribモジュール同様の手順でmake &&

make installして利用可能– PostgreSQLのバージョン毎にコードがある– PostgreSQL 9.3用はHEADを使う

● テーブル、インデックスのファイルをインップットし、ページヘッダやタプルヘッダのメタ情報の調査に有用

Page 18: 20140531 JPUGしくみ+アプリケーション分科会 勉強会資料

pg_filedumpの出力例(テーブル)pg_filedump -i /Users/postgres/base/pgsql934/base/12297/16486

Block 0 ********************************************************<Header> ----- Block Offset: 0x00000000 Offsets: Lower 40 (0x0028) Block: Size 8192 Version 4 Upper 8064 (0x1f80) LSN: logid 0 recoff 0x01f88dc8 Special 8192 (0x2000) Items: 4 Free Space: 8024 Checksum: 0x0000 Prune XID: 0x00000446 Flags: 0x0000 () Length (including item array): 40

<Data> ------ Item 1 -- Length: 32 Offset: 8160 (0x1fe0) Flags: NORMAL XMIN: 1091 XMAX: 0 CID|XVAC: 0 Block Id: 0 linp Index: 1 Attributes: 2 Size: 24 infomask: 0x0802 (HASVARWIDTH|XMAX_INVALID)

Page 19: 20140531 JPUGしくみ+アプリケーション分科会 勉強会資料

pg_filedumpの出力例(インデックス)Block 1 ********************************************************<Header> ----- Block Offset: 0x00002000 Offsets: Lower 40 (0x0028) Block: Size 8192 Version 4 Upper 8112 (0x1fb0) LSN: logid 0 recoff 0x01f89058 Special 8176 (0x1ff0) Items: 4 Free Space: 8072 Checksum: 0x0000 Prune XID: 0x00000000 Flags: 0x0000 () Length (including item array): 40

<Data> ------ Item 1 -- Length: 16 Offset: 8160 (0x1fe0) Flags: NORMAL Block Id: 0 linp Index: 1 Size: 16 Has Nulls: 0 Has Varwidths: 0

<Special Section> ----- BTree Index Section: Flags: 0x0043 (LEAF|ROOT|HASGARBAGE) Blocks: Previous (0) Next (0) Level (0) CycleId (0)

Page 20: 20140531 JPUGしくみ+アプリケーション分科会 勉強会資料

pageinspect vs pg_filedump● どちらも大体同じ情報が取れるが、pageinspect

に分がある感じ● pageinspectの良さ

– SQLで集計や検索が容易– テーブルやインデックス名で情報をひける

● pg_filedumpの良さ– PostgreSQLが停止してても使える– infomask等を分かりやすく表示する– インデックスのFlagの状態が分かる

● ただ、pg_filedumpはメンテが止まる可能性が・・– 9.3も正式版?が出ていない・・

Page 21: 20140531 JPUGしくみ+アプリケーション分科会 勉強会資料

pg_xlogdump● contribに付属しているツール● contribモジュールのmakeないしはRPMパッ

ケージ等で導入● コマンドライン● WALファイルをインップットし、トランザク

ションレコードの調査が可能● おそらくWALの内部情報を分かりやすくダンプ

する唯一のツール

Page 22: 20140531 JPUGしくみ+アプリケーション分科会 勉強会資料

pg_xlogdumpの出力例pg_xlogdump base/pgsql934/pg_xlog/000000010000000000000001

rmgr: Heap len (rec/tot): 35/ 67, tx: 1000, lsn: 0/01B25020, prev 0/01B24FE0, bkp: 0000, desc: insert(init): rel 1663/12297/16384; tid 0/1

rmgr: Transaction len (rec/tot): 12/ 44, tx: 1000, lsn: 0/01B25068, prev 0/01B25020, bkp: 0000, desc: commit: 2014-04-26 19:51:36.311101 JST

rmgr(resource manager)は処理カテゴリのようなもの。len は rec:rmgrに関連するもののみのレコード長

totはトランザクションレコード全体の長さ。txはトランザクションID

bkp はフルページのバックアップをしたかのフラグ。descはトランザクションの処理内容

Page 23: 20140531 JPUGしくみ+アプリケーション分科会 勉強会資料

pg_xlogdump 活用方法?● 運用でお世話になることは少ない・・● フルページの割合の調査には有用か

– Bkpフラグ等で確認できる● rmgrで絞れば、例えばテーブルの

CREATE/DROPなどを抽出できる– 大事なデータやテーブルの削除処理が分かるので、

オペミスからの復旧に使える– 大事な作業はログを取っておくものなので、出番は

ないかも・・

Page 24: 20140531 JPUGしくみ+アプリケーション分科会 勉強会資料

pg_xlogdump 活用方法?pg_xlogdump -r Storage …

rmgr: Storage len (rec/tot): 16/ 48, tx: 0, lsn: 0/0227AA20, prev 0/0227A9F0,bkp: 0000, desc: file create: base/12297/16505

Page 25: 20140531 JPUGしくみ+アプリケーション分科会 勉強会資料

挙動を見てみよう その1● Btreeのリーフスプリット

● Btreeインデックスのスプリットは● 一番右端のリーフは左をFILLFACTORぶん詰める● それ以外は1:1の比率で分ける

リーフ分割

右はなるべく空ける

Page 26: 20140531 JPUGしくみ+アプリケーション分科会 勉強会資料

見てみるcreate table test (c1 int);

CREATE INDEX test_idx ON test(c1);

INSERT into test SELECT generate_series(1,1000);SELECT (bt_page_stats('test_idx', i)).blkno,(bt_page_stats('test_idx', i)).type, (bt_page_stats('test_idx', i)).live_items, (bt_page_stats('test_idx', i)).btpo_prev, (bt_page_stats('test_idx', i)).btpo_next FROM (SELECT generate_series(1, relpages-1) from pg_class WHERE relname = 'test_idx')s(i);

blkno | type | live_items | btpo_prev | btpo_next

-------+------+------------+-----------+-----------

1 | l | 367 | 0 | 2

2 | l | 367 | 1 | 4

3 | r | 3 | 0 | 0

4 | l | 268 | 2 | 0

Page 27: 20140531 JPUGしくみ+アプリケーション分科会 勉強会資料

見てみるINSERT INTO test SELECT 1 FROM generate_series(1,100);

blkno | type | live_items | btpo_prev | btpo_next

-------+------+------------+-----------+-----------

1 | l | 251 | 0 | 5

2 | l | 367 | 5 | 4

3 | r | 4 | 0 | 0

4 | l | 268 | 2 | 0

5 | l | 217 | 1 | 2

左のリーフがスプリットされ251:217のキーを保持

Page 28: 20140531 JPUGしくみ+アプリケーション分科会 勉強会資料

見てみるINSERT INTO test SELECT 1000 FROM generate_series(1,200);

blkno | type | live_items | btpo_prev | btpo_next

-------+------+------------+-----------+-----------

1 | l | 251 | 0 | 5

2 | l | 367 | 5 | 4

3 | r | 5 | 0 | 0

4 | l | 407 | 2 | 6

5 | l | 217 | 1 | 2

6 | l | 62 | 4 | 0

右端のリーフがスプリットされ407:62のキーを保持

Page 29: 20140531 JPUGしくみ+アプリケーション分科会 勉強会資料

挙動を見てみよう その2● Commit Hint Bit

● INSERTやUPDATEで新規のデータが投入される● そのトランザクションがコミットされる● 別のトランザクションがその新規のデータを見る● その際、本当にコミットされたかをコミットログから判断する● コミットされていたらフラグを立て、以降はフラグで判断する● これがCommit Hint Bit

タプルヘッダ 実データTx A

Tx B

INSERT & COMMIT

clog

見に行くHintないClog見る

Commitされてた。フラグ付ける

Page 30: 20140531 JPUGしくみ+アプリケーション分科会 勉強会資料

見てみる● 簡単なデモで

Page 31: 20140531 JPUGしくみ+アプリケーション分科会 勉強会資料

終わりに● PostgreSQLのデータ構成とツールの一部を紹

介しました● データの作りや変更を追っていく

と、PostgreSQLの中が見えてきます● バイナリエディタやgdbを駆使するのもアリで

すが、便利なツールもあります● 是非使ってみてください!

Page 32: 20140531 JPUGしくみ+アプリケーション分科会 勉強会資料

ご清聴ありがとうございました!QA?