Re: simplifying foreign key/RI checks
От | Tom Lane |
---|---|
Тема | Re: simplifying foreign key/RI checks |
Дата | |
Msg-id | 1627848.1636676261@sss.pgh.pa.us обсуждение исходный текст |
Ответ на | simplifying foreign key/RI checks (Amit Langote <amitlangote09@gmail.com>) |
Список | pgsql-hackers |
Alvaro Herrera <alvherre@2ndquadrant.com> writes: > I think we (I) should definitely pursue fixing whatever was broken by > DETACH CONCURRENTLY, back to pg14, independently of this patch ... but > I would appreciate some insight into what the problem is. Here's what I'm on about: regression=# create table pk (f1 int primary key); CREATE TABLE regression=# insert into pk values(1); INSERT 0 1 regression=# create table fk (f1 int references pk); CREATE TABLE regression=# begin isolation level repeatable read ; BEGIN regression=*# select * from pk; -- to establish xact snapshot f1 ---- 1 (1 row) now, in another session, do: regression=# insert into pk values(2); INSERT 0 1 back at the RR transaction, we can't see that: regression=*# select * from pk; -- still no row 2 f1 ---- 1 (1 row) so we get: regression=*# insert into fk values(1); INSERT 0 1 regression=*# insert into fk values(2); ERROR: insert or update on table "fk" violates foreign key constraint "fk_f1_fkey" DETAIL: Key (f1)=(2) is not present in table "pk". IMO that behavior is correct. If you use READ COMMITTED, then SELECT can see row 2 as soon as it's committed, and so can the FK check, and again that's correct. In v13, the behavior is the same if "pk" is a partitioned table instead of a plain one. In HEAD, it's not: regression=# drop table pk, fk; DROP TABLE regression=# create table pk (f1 int primary key) partition by list(f1); CREATE TABLE regression=# create table pk1 partition of pk for values in (1,2); CREATE TABLE regression=# insert into pk values(1); INSERT 0 1 regression=# create table fk (f1 int references pk); CREATE TABLE regression=# begin isolation level repeatable read ; BEGIN regression=*# select * from pk; -- to establish xact snapshot f1 ---- 1 (1 row) --- now insert row 2 in another session regression=*# select * from pk; -- still no row 2 f1 ---- 1 (1 row) regression=*# insert into fk values(1); INSERT 0 1 regression=*# insert into fk values(2); INSERT 0 1 regression=*# So I say that's busted, and the cause is this hunk from 71f4c8c6f: @@ -392,11 +392,15 @@ RI_FKey_check(TriggerData *trigdata) /* * Now check that foreign key exists in PK table + * + * XXX detectNewRows must be true when a partitioned table is on the + * referenced side. The reason is that our snapshot must be fresh + * in order for the hack in find_inheritance_children() to work. */ ri_PerformCheck(riinfo, &qkey, qplan, fk_rel, pk_rel, NULL, newslot, - false, + pk_rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE, SPI_OK_SELECT); if (SPI_finish() != SPI_OK_FINISH) I think you need some signalling mechanism that's less global than ActiveSnapshot to tell the partition-lookup machinery what to do in this context. regards, tom lane
В списке pgsql-hackers по дате отправления:
Предыдущее
От: "Euler Taveira"Дата:
Сообщение: Re: [BUG]Invalidate relcache when setting REPLICA IDENTITY