如何在 postgres 中执行幻读?
How can I enforce a phantom read in postgres?
我目前正在写一篇关于不同事务隔离级别的文章,想展示脏读/不可重复读/幻读。
脏读无法显示,因为 PostgreSQL 没有 READ_UNCOMMITTED,我有一个不可重复读的例子。但是,我很难找到幻读的例子。
作为示例,我创建了这个:
CREATE TABLE balances (id varchar PRIMARY KEY, balance int);
INSERT INTO balances (id, balance) VALUES ('Alice', 40), ('Bob', 50);
然后我有两个终端(T1 和 T2)连接到数据库来执行此操作:
T1$ start transaction isolation level repeatable read;
T1$ SELECT * FROM balances WHERE balance > 10;
id | balance
----------+---------
Alice | 40
Bob | 50
T2$ INSERT INTO balances (id, balance) VALUES ('Charlie', 60);
T1$ SELECT * FROM balances WHERE balance > 10;
id | balance
----------+---------
Alice | 40
Bob | 50
为什么这不会产生幻读?我认为最后一个 T1-Query 应该显示查理,但事实并非如此。我认为只有 SERIALIZABLE 事务隔离级别才会出现这种情况。 REPEATABLE READ 是否也能防止 PostgreSQL 中的幻读?
在 Postgres 12 中,REPEATABLE_READ 事务隔离级别可防止幻读 (source)。
我目前正在写一篇关于不同事务隔离级别的文章,想展示脏读/不可重复读/幻读。
脏读无法显示,因为 PostgreSQL 没有 READ_UNCOMMITTED,我有一个不可重复读的例子。但是,我很难找到幻读的例子。
作为示例,我创建了这个:
CREATE TABLE balances (id varchar PRIMARY KEY, balance int);
INSERT INTO balances (id, balance) VALUES ('Alice', 40), ('Bob', 50);
然后我有两个终端(T1 和 T2)连接到数据库来执行此操作:
T1$ start transaction isolation level repeatable read;
T1$ SELECT * FROM balances WHERE balance > 10;
id | balance
----------+---------
Alice | 40
Bob | 50
T2$ INSERT INTO balances (id, balance) VALUES ('Charlie', 60);
T1$ SELECT * FROM balances WHERE balance > 10;
id | balance
----------+---------
Alice | 40
Bob | 50
为什么这不会产生幻读?我认为最后一个 T1-Query 应该显示查理,但事实并非如此。我认为只有 SERIALIZABLE 事务隔离级别才会出现这种情况。 REPEATABLE READ 是否也能防止 PostgreSQL 中的幻读?
在 Postgres 12 中,REPEATABLE_READ 事务隔离级别可防止幻读 (source)。