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时间?
select
insert
commit
答案确实取决于服务器的实现以及唯一约束是否标记为可延迟。
我没有针对其他数据库进行过测试,但是在PostgreSQL(作为最著名的开源MVCC数据库之一)中,在我的测试中,复制设置T2失败INSERT。但是,T2无法使用来查看T1所做的任何更改SELECT。
INSERT
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时检查唯一性:
如果唯一性约束是可延迟的,那么还会有额外的复杂性:我们需要能够为新行插入索引条目,但是将任何违反唯一性的错误推迟到语句结束时或更晚。