小编典典

MVCC数据库在交易中是否看到插入的行?

sql

MVCC数据库隔离模式是否允许正在进行的事务查看其他事务插入(和提交)的行?

例如,给定:

  • names[id BIGINT NOT NULL, name VARCHAR(30), PRIMARY KEY(id), UNIQUE(name)]
  • 交易T1和T2,

    T1: open transaction
    T2: open transaction
    T1: select * from names;
    insert into names(name) values(“John”);
    // do something
    commit;
    T2: select * from names;
    insert into names values(“John”);
    // do something
    commit;

T2什么时候第一次知道新行?在select时间?在insert时间?还是在某个commit时间?


阅读 162

收藏
2021-05-30

共1个答案

小编典典

答案确实取决于服务器的实现以及唯一约束是否标记为可延迟。

我没有针对其他数据库进行过测试,但是在PostgreSQL(作为最著名的开源MVCC数据库之一)中,在我的测试中,复制设置T2失败INSERT。但是,T2无法使用来查看T1所做的任何更改SELECT

我几乎同时在2个独立的SQL连接中执行了以下语句:

BEGIN;
SELECT * FROM names;
SELECT pg_sleep(10);
INSERT INTO names values('john');
SELECT pg_sleep(10);
COMMIT;

一个成功,但是另一个失败在10秒后,具有:

ERROR:  duplicate key value violates unique constraint "names_pkey"
DETAIL:  Key (name)=(john) already exists.

这是有道理的,因为文档说:

如果尚未提交的事务已插入有冲突的行,则可能的插入程序必须等待以查看该事务是否已提交。如果回滚,则没有冲突。如果提交但未再次删除冲突的行,则表示存在唯一性冲突。

但是,如果将唯一性约束标记为可延迟,则将在COMMIT时检查唯一性:

如果唯一性约束是可延迟的,那么还会有额外的复杂性:我们需要能够为新行插入索引条目,但是将任何违反唯一性的错误推迟到语句结束时或更晚。

2021-05-30