PostgreSQLスキルアップノート(自己啓発のための個人サイト)

データベースページの解析「pageinspect」その1


【一覧に戻る】
マニュアルへのリンクは/9.2/としています。


━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
■■■■ PostgreSQL スキルアップノート
■■■■
■◆■■ データベースページの解析「pageinspect」その1
■■■■
■■■■
■■■■ 使用環境:PostgreSQL9.2.3 (CentOS6.2)
         2013/03/23
                                                                   (C) 2013 ohdb
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

pageinspectはデータベースページの解析に使用するツール(関数群)。


【マニュアル】

付録 F. 追加で提供されるモジュール・pageinspect→●[マニュアル]

【参考記事】
 −



■1■ インストール
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

利用可能な拡張(Extension)であることを確認

【□】 psql database1 -c "select * from pg_available_extensions where name = 'pageinspect'"

    name     | default_version | installed_version |                        comment
-------------+-----------------+-------------------+-------------------------------------------------------
 pageinspect | 1.0             |                   | inspect the contents of database pages at a low level



CREATE EXTENSIONを実行してインストール
インストールは解析が必要なDBに対して行う。

【□】 psql database1 -c "CREATE EXTENSION pageinspect"



インストール後の確認

【□】 psql database1 -c "select * from pg_available_extensions where name = 'pageinspect'"

    name     | default_version | installed_version |                        comment
-------------+-----------------+-------------------+-------------------------------------------------------
 pageinspect | 1.0             | 1.0 ★            | inspect the contents of database pages at a low level



設定等は特に不要。





■2■ 予備知識・データベースページのイメージ
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

以下は bufpage.h (src/include/storage/bufpage.h)のコメント行をもとに作成。


   イメージ(1ページ8192バイト)
  ┌─────────────────────┐
  │ PageHeaderData linp1,linp2,linp3 ・・・  │
  │ ・・・・・・・linpN                      │
  │         ↓     ↓     ↓     ↓          │
  │       行ポインタ(ラインポインタ)       │
  │         ↓     ↓     ↓     ↓          │
  │                                          │
  │                                          │
  │                                          │
  │         ↑     ↑     ↑     ↑          │
  │                                          │
  │         ↑     ↑     ↑     ↑          │
  │               行データ                   │
  │         ↑     ↑     ↑     ↑          │
  │                                          │
  │         ↑     ↑     ↑     ↑          │
  │                                          │
  │          tupleN   ・・・・・・・・       │
  │  tuple8               tuple7             │
  │     tuple6      tuple5     tuple4        │
  │          tuple3      tuple2      tuple1  │
  └─────────────────────┘
   一部の構成要素を省略




■3■ 提供される関数群
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

本ページで取り上げるのは以下の○印のもの

○get_raw_page(relname text[,fork text],blkno int)  指定されたテーブルの指定されたブロックの内容
 page_header(page bytea)                           ページヘッダを表示(ヒープとインデックスページとも)
○heap_page_items(page bytea)                       ヒープページ上の行ポインタ、タプルヘッダの情報
 bt_metap(relname text)                            B-treeインデックスのメタページに関する情報
 bt_page_stats(relname text, blkno int)            B-treeインデックスの個別のページ要約情報
 bt_page_items(relname text, blkno int)            B-treeインデックスページ上の全項目についての詳細情報
 fsm_page_contents(page bytea)                     FSMページの内部ノード構造




■4■ get_raw_page関数
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

・指定した1ブロックの内容を16進で出力する関数。
・出力は1行1カラムで改行なし。
・テーブル名とブロック番号を引数に与える。


【□】 SELECT get_raw_page('t1',0);

 \x0a000000303df67b01000100e000a81f002004200000000〜〜・・・8K分の内容が1行で出力される。

結果は8KBが1行として出力され、扱いづらいため整形用のスクリプトを作成した。
詳細は別ページにて。→●[サイト内]


 (参考)その他の指定

   1)テーブルデータ(主データフォーク) SELECT get_raw_page('t1','main',0);
   2)空き領域マップ                     SELECT get_raw_page('t1','fsm',0);
   3)可視性マップを指定                 SELECT get_raw_page('t1','vm',0);

   1)はSELECT get_raw_page('t1',0) と同じ意味。
   テーブルデータを対象にする場合はmainの指定を省略できる。
   



■5■ heap_page_items関数
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

heap_page_itemsは行ポインタの情報を取り出すもの。

こちらについてもスクリプトを用意してデータベースページの内容とセットで出力を行うようにした。
詳細は別ページにて。→●[サイト内]


【□】 SELECT * FROM heap_page_items(get_raw_page('t1','main',0));


 lp | lp_off | lp_flags | lp_len | t_xmin | t_xmax | t_field3 | t_ctid | t_infomask2 | t_infomask | t_hoff | t_bits | t_oid
----+--------+----------+--------+--------+--------+----------+--------+-------------+------------+--------+--------+-------
  1 |   8104 |        1 |     87 |   2557 |   2560 |        0 | (0,1)  |           3 |        258 |     24 |        |
  2 |   8016 |        1 |     87 |   2558 |      0 |        0 | (0,2)  |           3 |       2306 |     24 |        |
  3 |   7928 |        1 |     87 |   2559 |      0 |        0 | (0,3)  |           3 |       2306 |     24 |        |



lp        ラインポインタ(行ポインタ)
pl_off    ブロック内の位置(オフセット)
t_xmin    行を作成したトランザクションID
t_xmax    行を削除したトランザクションID
lp_flags  itemid.hに記載されている。
          0  LP_UNUSED     /* unused */
          1  LP_NORMAL     /* used   */
          2  LP_REDIRECT   /* HOT redirect (should have lp_len=0) */
          3  LP_DEAD       /* dead, may or may not have storage */

・普通のデータ      lp_flags=1
・DELETEされたもの  lp_flags=1   lp_flagsではなくt_xmaxに値が入っているもので判別する。 
・VACUUMで回収された場合、lp_flagsは0となる。
・HOTによるリダイレクト(付け替え)が発生した場合、lp_flagsは2となる。(下記参照)
  このときのlp_offはバイト位置ではなくリダイレクト先の行ポインタの番号が入るので注意。

以下の結果でlp=2のlp_flagsは2なので、これはリダイレクトされた行ポインタである。
リダイレクト先は、lp=4である。
しかしlp=4はt_xmaxに値が入っているので既に削除された行の行ポインタである。

lp=3についても同様に、リダイレクト先はlp=50である。


database1=# SELECT * FROM heap_page_items(get_raw_page('t1','main',0));
 lp | lp_off | lp_flags | lp_len | t_xmin | t_xmax | t_field3 | t_ctid | t_infomask2 | t_infomask | t_hoff | t_bits | t_oid
----+--------+----------+--------+--------+--------+----------+--------+-------------+------------+--------+--------+-------
  1 |   7928 |        1 |     85 |   2609 |   2610 |        0 | (0,5)  |       49155 |       9474 |     24 |        |
  2 |  ★  4 |     → 2 |      0 |        |        |          |        |             |            |        |        |
  3 |  ● 50 |     → 2 |      0 |        |        |          |        |             |            |        |        |
★4 |   8104 |        1 |     85 |   2561 |   2614 |        0 | (0,4)  |       32771 |       8450 |     24 |        |
  5 |   7840 |        1 |     85 |   2610 |   2611 |        0 | (0,6)  |       49155 |       9474 |     24 |        |
  6 |   7752 |        1 |     85 |   2611 |   2612 |        0 | (0,7)  |       49155 |       9474 |     24 |        |
  7 |   7664 |        1 |     85 |   2612 |   2613 |        0 | (0,8)  |       49155 |       9474 |     24 |        |
  8 |   7576 |        1 |     85 |   2613 |      0 |        0 | (0,8)  |       32771 |      10498 |     24 |        |
  9 |      0 |        0 |      0 |        |        |          |        |             |            |        |        |
 10 |      0 |        0 |      0 |        |        |          |        |             |            |        |        |
   :         :            :
   :         :            :
 46 |      0 |        0 |      0 |        |        |          |        |             |            |        |        |
 47 |      0 |        0 |      0 |        |        |          |        |             |            |        |        |
 48 |      0 |        0 |      0 |        |        |          |        |             |            |        |        |
 49 |      0 |        0 |      0 |        |        |          |        |             |            |        |        |
●50|   8016 |        1 |     85 |   2607 |   2609 |        0 | (0,1)  |       49155 |       9474 |     24 |        |

                                                                                                            
以上 
inserted by FC2 system