How to enforce a phantom read in PostgreSQL?

855 views Asked by At

I'm currently writing an article about different transaction isolation levels and want to show the dirty read / non-repeatable read / phantom read.

Dirty reads are impossible to show as PostgreSQL does not have READ_UNCOMMITTED, I do have an example for a non-repeatable read. However, I struggle with finding an example for a phantom read.

As an example, I create this:

CREATE TABLE balances (id varchar PRIMARY KEY, balance int);
INSERT INTO balances (id, balance) VALUES ('Alice', 40), ('Bob', 50);

Then I have two terminals (T1 and T2) with which I connect to the database to do this:

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   

Why does this not give a phantom read? I thought the last T1-Query should show Charlie, but it doesn't. I thought that would only be the case with the SERIALIZABLE transaction isolation level. Does REPEATABLE READ also prevent phantom reads in PostgreSQL?

2

There are 2 answers

0
Martin Thoma On BEST ANSWER

In Postgres 12, the REPEATABLE_READ transaction isolation level prevents phantom reads (source).

0
Super Kai - Kazuya Ito On

In PostgreSQL, REPEATABLE_READ prevents phantom read. This is my answer on Stack Overflow which has the example of phantom read and this is also my answer on Stack Overflow which experiments if phantom read occurs in REPEATABLE READ in PostgreSQL.