我试图更好地理解 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 的角度来看,所有 txids < 704 都是不活动的(提交或中止)并且所有事务 > = 704 个处于活动状态(进行中或尚未开始)。
会话 1 的第二个查询将获得 704:706 的新快照:这意味着从 txid 704 的角度来看,所有 txids < 704 都处于非活动状态,并且所有 txids >= 706 都处于活动状态。然而,由于 txid 705 介于这些值之间,并且它实际上已经提交,它也是 txid 704 收到的新快照的一部分,并且是可见的。因此,一个元组只有在其 xmin 小于当前交易的 txid 时才可见并不是硬性规定。