最も単純なケースでは、新しい行をテーブルに挿入すると(そしてトランザクションがコミットすると)、後続のすべてのトランザクションから見えるようになります。xmax
この例では0であることを参照してください。
CREATE TABLE vis (
id serial,
is_active boolean
);
INSERT INTO vis (is_active) VALUES (FALSE);
SELECT ctid, xmin, xmax, * FROM vis;
ctid │xmin │ xmax │ id │ is_active
───────┼─────┼──────┼────┼───────────
(0,1) │2699 │ 0 │ 1 │ f
これを更新すると(フラグがFALSE
誤って設定されたため)、少し変更されます。
UPDATE vis SET is_active = TRUE;
SELECT ctid, xmin, xmax, * FROM vis;
ctid │ xmin │ xmax │ id │ is_active
──────┼──────┼──────┼────┼───────────
(0,2) │ 2700 │ 0 │ 1 │ t
PostgreSQLが使用するMVCCモデルによると、新しい物理行が書き込まれ、古い行が無効化されました(これはから確認できますctid
)。新しいトランザクションは、後続のすべてのトランザクションで引き続き表示されます。
ここで、ロールバックすると興味深いことが起こりUPDATE
ます。
BEGIN;
UPDATE vis SET is_active = TRUE;
ROLLBACK;
SELECT ctid, xmin, xmax, * FROM vis;
ctid │ xmin │ xmax │ id │ is_active
───────┼──────┼──────┼────┼───────────
(0,2) │ 2700 │ 2702 │ 1 │ t
行バージョンは同じままですが、現在xmax
は何かに設定されています。これにもかかわらず、後続のトランザクションはこの(そうでなければ変更されていない)行を見ることができます。
これについて少し読んだ後、行の可視性についていくつかのことを理解できます。可視性マップがありますが、ページ全体が表示されているかどうかのみがわかります。行(タプル)レベルでは機能しません。次に、コミットログ(別名clog
)がありますが、Postgres は、ログにアクセスする必要があるかどうかをどのように判断しますか?
情報マスクのビットを見て、可視性が実際にどのように機能するかを理解することにしました。それらを表示する最も簡単な方法は、pageinspect拡張機能を使用することです。設定されているビットを確認するために、それらを格納するテーブルを作成しました。
CREATE TABLE infomask (
i_flag text,
i_bits bit(16)
);
INSERT INTO infomask
VALUES
('HEAP_HASNULL', x'0001'::bit(16)),
('HEAP_HASVARWIDTH', x'0002'::bit(16)),
('HEAP_HASEXTERNAL', x'0004'::bit(16)),
('HEAP_HASOID', x'0008'::bit(16)),
('HEAP_XMAX_KEYSHR_LOCK', x'0010'::bit(16)),
('HEAP_COMBOCID', x'0020'::bit(16)),
('HEAP_XMAX_EXCL_LOCK', x'0040'::bit(16)),
('HEAP_XMAX_LOCK_ONLY', x'0080'::bit(16)),
('HEAP_XMIN_COMMITTED', x'0100'::bit(16)),
('HEAP_XMIN_INVALID', x'0200'::bit(16)),
('HEAP_XMAX_COMMITTED', x'0400'::bit(16)),
('HEAP_XMAX_INVALID', x'0800'::bit(16)),
('HEAP_XMAX_IS_MULTI', x'1000'::bit(16)),
('HEAP_UPDATED', x'2000'::bit(16)),
('HEAP_MOVED_OFF', x'4000'::bit(16)),
('HEAP_MOVED_IN', x'8000'::bit(16)),
('HEAP_XACT_MASK', x'FFF0'::bit(16));
次に、私のvis
テーブルのpageinspect
内容を確認しました。これはヒープの物理的な内容を示しているため、表示されている行だけが返されるわけではありません。
SELECT t_xmin, t_xmax, string_agg(i_flag, ', ') FILTER (WHERE (t_infomask::bit(16) & i_bits)::integer::boolean)
FROM heap_page_items(get_raw_page('vis', 0)),
infomask
GROUP BY t_xmin, t_xmax;
t_xmin │ t_xmax │ string_agg
────────┼────────┼──────────────────────────────────────────────────────
2699 │ 2700 │ HEAP_XMIN_COMMITTED, HEAP_XMAX_COMMITTED
2700 │ 2702 │ HEAP_XMIN_COMMITTED, HEAP_XMAX_INVALID, HEAP_UPDATED
2702 │ 0 │ HEAP_XMIN_INVALID, HEAP_XMAX_INVALID, HEAP_UPDATED
私は上記から理解することは、最初のバージョンは、トランザクション2699との生活に来て、そして成功した2700の新しいバージョンに置き換えられていることである
その後2700年以来、生きていた次の1、、の圧延バックの試みを持っていたUPDATE
から見て、2702年にHEAP_XMAX_INVALID
。
で示されているように、最後のものは実際には決して生まれませんでしたHEAP_XMIN_INVALID
。
したがって、上記から推測すると、最初と最後のケースは明白です-それらはトランザクション2703以降ではもう見えません。
2つ目はどこかで検索する必要がありますclog
。これは、コミットログ(別名)だと思います。
問題をさらに複雑にするために、その後のUPDATE
結果は次のようになります。
t_xmin │ t_xmax │ string_agg
────────┼────────┼────────────────────────────────────────────────────
2699 │ 2700 │ HEAP_XMIN_COMMITTED, HEAP_XMAX_COMMITTED
2702 │ 0 │ HEAP_XMIN_INVALID, HEAP_XMAX_INVALID, HEAP_UPDATED
2703 │ 0 │ HEAP_XMAX_INVALID, HEAP_UPDATED
2700 │ 2703 │ HEAP_XMIN_COMMITTED, HEAP_UPDATED
ここでは、表示可能な候補がすでに2つあります。だから、最後に、これが私の質問です:
- 私の仮定は、
clog
これらの場合に可視性を判断するために注目すべき場所であるということですか? - どのフラグ(またはフラグの組み合わせ)がシステムに
clog
? - 中身を調べる方法はあり
clog
ますか?clog
以前のバージョンのPostgresの破損についての言及と、偽のファイルを手動で作成できるというヒントがあります。この情報は、それをサポートするのに役立ちます。