I play around with Postgres serializable mode, and found some commit order that fail a transaction, but wont fail a transaction in case of different commit ordering.
For below code, I run from each transaction concurrently, but do operation on each transaction step-by-step, so I start tx 1 and complete all of its ops, then tx 2 and all of its ops, then tx 3. But after each succession I do not commit it yet. After all ops on all tx completes then I start commiting.
Table Declarations:
drop table if exists si_test;
create table si_test (name text unique, num integer);
insert into si_test values('a',10);
insert into si_test values('b',20);
insert into si_test values('c',30);
The transactions:
T1: begin transaction isolation level serializable;
T1: update si_test set num=45 where name='a';
T2: begin transaction isolation level serializable;
T2: select * from si_test where name='a'; -- -> this shows value 10
T2: update si_test set num=47 where name='b';
T3: begin transaction isolation level serializable;
T3: select * from si_test where name='b'; -- -> this shows value 20
And this is my commit order and result:
T1 -> T3 -> T2 : T2 serialization error
T1 -> T2 -> T3 : T2 serialization error
T2 -> T1 -> T3 : all committed
T2 -> T3 -> T1 : all committed
T3 -> T1 -> T2 : all committed
T3 -> T2 -> T1 : all committed
From those queries, I can say that there is a serializable schedule T3 -> T2 -> T1. I read at postgres SSI docs that they check for 2 "dangerous structure / rw-dependency" to conclude if some concurrent transactions will violate a serializable schedule, which from my tests, should not be.
I have checked the EXPLAIN ANALYZE, and it shows that my instance is using index scan to satisfy the where clause
My question is: Can someone explain what actually is going on? Where is the catch in my test?
Notes: Test run on Postgres 11.2 on Windows 10 Pro
Notes 2: Those 3 tx run on 3 different connection at once