I was trying to figure out what exactly the "crosscheck snapshot" does in the RI checks, and hit some assertion failures:
postgres=# create table p(i int primary key); CREATE TABLE postgres=# create table f (i int references p on delete cascade on update cascade deferrable initially deferred); CREATE TABLE postgres=# insert into p values (1); INSERT 0 1 postgres=# begin isolation level repeatable read; BEGIN postgres=*# table f; i --- (0 rows) In another session: postgres=# insert into f values (1); INSERT 0 1 Back in the first session: postgres=*# delete from p where i=1; TRAP: FailedAssertion("!(tp.t_data->t_infomask & HEAP_XMAX_INVALID)", File: "heapam.c", Line: 2652) I'm not familiar enough with this code but I wonder if it's only about incorrect assertions. When I commented out some, I got error message that makes sense to me: postgres=*# delete from p where i=1; 2020-03-17 11:59:19.214 CET [89379] ERROR: could not serialize access due to concurrent update 2020-03-17 11:59:19.214 CET [89379] CONTEXT: SQL statement "DELETE FROM ONLY "public"."f" WHERE $1 OPERATOR(pg_catalog.=) "i"" 2020-03-17 11:59:19.214 CET [89379] STATEMENT: delete from p where i=1; ERROR: could not serialize access due to concurrent update CONTEXT: SQL statement "DELETE FROM ONLY "public"."f" WHERE $1 OPERATOR(pg_catalog.=) "i"" Similarly, if the test ends with an UPDATE statement, I get this failure: postgres=*# update p set i=i+1 where i=1; TRAP: FailedAssertion("!ItemPointerEquals(&oldtup.t_self, &oldtup.t_data->t_ctid)", File: "heapam.c", Line: 3275) Likewise, with the Assert() statements commented out, the right thing seems to happen: 2020-03-17 11:57:04.810 CET [88678] ERROR: could not serialize access due to concurrent update 2020-03-17 11:57:04.810 CET [88678] CONTEXT: SQL statement "UPDATE ONLY "public"."f" SET "i" = $1 WHERE $2 OPERATOR(pg_catalog.=) "i"" 2020-03-17 11:57:04.810 CET [88678] STATEMENT: update p set i=i+1 where i=1; ERROR: could not serialize access due to concurrent update CONTEXT: SQL statement "UPDATE ONLY "public"."f" SET "i" = $1 WHERE $2 OPERATOR(pg_catalog.=) "i"" -- Antonin Houska Web: https://www.cybertec-postgresql.com