-- connect to the database: psql postgres -- create a database called test and connect to it: create database test; \c test; -- add some data: create table account(name varchar primary key, balance int); insert into account values ('Alice', 500); insert into account values ('Bob', 500); select * from account; select sum(balance) from account; -- open a long-running transaction: begin transaction; update account set balance=balance-100 where name='Alice'; select * from account; -- launch another client: psql test -- in the 2nd client, inspect the table: select * from account; -- exit the 2nd client: \q -- exit the 1st client: \q -- relaunch a client: psql test select * from account; -- no change -- restart the transaction: begin transaction; update account set balance=balance-100 where name='Alice'; -- stop the server pg_ctl stop -D ~/pg14data -- how is the client doing? -- restart the server pg_ctl start -D ~/pg14data -- relaunch the client psql test select * from account; -- no change -- now let's see how constraint satisfaction is impacted by transactions create table client(name varchar primary key, city varchar); delete from account; alter table account add constraint name_fk foreign key(name) references client(name) deferrable; -- note that the constraint is deferrable; -- put some data in client: insert into client values('Alice', 'Paris'); -- try to put back data in account insert into account values ('Alice', 500); -- ok insert into account values ('Bob', 500); -- doesn't work! we will open a long-running transaction, to move the checks at the end: begin transaction; set constraints all deferred; insert into account values ('Bob', 500); -- this works! select * from account; -- in another client, do select * from client; select * from account; -- come back to the first client: end transaction; -- now we do it again but correctly: begin transaction; set constraints all deferred; insert into account values ('Bob', 500); select * from account; insert into client values('Bob', 'Lyon'); select * from client; select * from account; end transaction; -- the default isolation level in PostgreSQL is read committed, which allows unrepeatable reads and phantom reads -- Next, we show an unrepeatable read. -- in one client: begin transaction; select * from account; -- now start another client: select * from account; begin transaction; update account set balance=balance+1; -- in the first client select * from account -- in the 2nd client end transaction; -- back to the 1st client: select * from account; -- we can relax the isolation level, or make it more strict. https://www.postgresql.org/docs/12/sql-set-transaction.html -- begin transaction isolation level read uncommitted;