web-dev-qa-db-ja.com

PostgreSQLのMVCC:xmin>現在のtxidを持つ可視タプル

私はMVCCをよりよく理解しようとしていますが、次の(考案された)シナリオに混乱しています。行がトランザクションに表示されるためには、トランザクションのIDがタプルのxmin値よりも大きくなければならないという印象を受けました。

_create table test (id int);

(session 1)
begin;
select txid_current();
┌──────────────┐
│ txid_current │
├──────────────┤
│          704 │
└──────────────┘

(session 2)
begin;
insert into test values (1);
commit;

(session 1)
select xmin, xmax, id from test;
┌──────┬──────┬────┐
│ xmin │ xmax │ id │
├──────┼──────┼────┤
│  705 │    0 │  1 │
└──────┴──────┴────┘
_

IDが704のトランザクションは、xminが705のタプルをどのように見ることができますか?

更新:

読む http://www.interdb.jp/pg/pgsql05.html 私にとって物事をより明確にするのに役立ちました。私が以前に見たいくつかのビデオは、厳格なルールとして、タプルはそのxminが現在のトランザクションのtxidよりも小さい場合にのみ表示されることを示唆しているように見えました。

しかし、上記の読書は私にとって少し異なる絵を描きました。 READ COMMITTEDの分離レベルでは、トランザクションは、各クエリの開始時に他のトランザクションの状態の新しいスナップショットを取得します。

セッション1の最初のクエリは704:704のスナップショットを取得します:(これはselect txid_current_snapshot()を実行することで確認できます)これは、txid 704の観点から、すべてのtxid <704が非アクティブ(コミット済み)であることを意味します。または中止)およびすべてのトランザクション> = 704がアクティブです(進行中またはまだ開始されていません)。

セッション1の2番目のクエリは、704:706の新しいスナップショットを取得します。これは、txid 704の観点から、すべてのtxid <704が非アクティブであり、すべてのtxid> = 706がアクティブであることを意味します。ただし、txid 705はこれらの値の間に収まり、実際にコミットされているため、txid 704が受信した新しいスナップショットの一部であり、表示されます。したがって、タプルが表示されるのは、そのxminが現在のトランザクションのtxidよりも小さい場合のみであるというのは難しい規則ではありません。

2
Dave Stibrany

これは、分離レベルによって異なります。 postgresqlのデフォルトレベルは「ReadCommitted」で、このレベルでこれが発生する可能性があります。 postgresqlでは、「RepeatableRead」または「Serializable」では発生しません。

多くの場合、この動作は問題ではなく、シリアル化レベルが高いとサーバーの速度が低下する可能性があります。これが、デフォルトではない理由です。

詳細な説明については、マニュアルを参照してください https://www.postgresql.org/docs/9.6/static/transaction-iso.html

1
Eelke

セッション1では、select txid_current();が古くなっています。セッション2が挿入を完了した後でそのクエリを繰り返すと、705より大きい別の値が返されることがわかります。

Txid_current()を所定の位置にロックする場合は、分離レベルを少なくとも繰り返し可能な読み取りに設定してトランザクションを実行する必要があります。それ以外の場合は、各ステートメント間を進みます(データベース内の他のコミットアクティビティが与えられた場合)。

0
jjanes