Re[2]: [BUGS] BUG #13935: Duplicate row in pg_constraint table which is not accessible via indexes

From: Alexey Makhmutov <bear2k(at)mail(dot)ru>
To: Tom Lane <tgl(at)sss(dot)pgh(dot)pa(dot)us>
Cc: pgsql-bugs(at)postgresql(dot)org, Alvaro Herrera <alvherre(at)2ndquadrant(dot)com>
Subject: Re[2]: [BUGS] BUG #13935: Duplicate row in pg_constraint table which is not accessible via indexes
Date: 2016-02-11 16:35:48
Message-ID: 1455208548.293188199@f437.i.mail.ru
Views: Raw Message | Whole Thread | Download mbox | Resend email
Thread:
Lists: pgsql-bugs

> > I wonder if you got into this state by adding primary keys concurrently
> > somehow. That should of course not be allowed, but of course there is
> > no UNIQUE constraint on conrelid itself, so the normal unique-ification
> > code in btree does not fire for this situation.
>
> I thought maybe Simon's changes to reduce lock levels in ALTER TABLE
> had gone too far, but simple experiment shows that ALTER ADD PRIMARY KEY
> commands still block each other (and then the second one fails as
> expected). So there isn't an obvious hole here.
>
> Given that the OIDs are different, it seems more likely that this is the
> result of a primary key being dropped and then re-created, and later
> somehow the commit state of the original row got reverted.

Yes, sure - sorry for the misleading phrasing. These two rows are not completely identical - their OIDs are different and reference to the supporting index is different:
# select oid,ctid,xmin,xmax,conrelid,contype,conindid from pg_constraint where conrelid::int+0=50621;
oid | ctid | xmin | xmax | conrelid | contype | conindid
--------+---------+---------+------+----------+---------+----------
301952 | (6,136) | 4883898 | 0 | 50621 | p | 301951
300466 | (7,1) | 4786734 | 0 | 50621 | p | 300465
(2 rows)

Of course, only one index exists - the one referenced by indexed row in pg_constraint. So, yes - it looks like this ‘phantom’ row wasn’t properly deleted.

This table is recreated in two steps - first, a script is executed via psql, which drops and recreate table structure using slightly weird PL/PgSQL fragment:
do $$
declare
begin
begin
execute 'drop table this_table';
exception
when undefined_table then null;
end;

begin
execute 'create table this_table
(
part_id NUMERIC(20),
restart_id CHARACTER VARYING(250),
restart_info BYTEA
)';
exception
when duplicate_table then null;
end;
end $$ language 'plpgsql';
Script invocation is wrapped into begin; .. commit; command. The script doesn't create PK.

And then Java application performs table modification (in separate transaction):
alter table this_table add key character varying(4000);
alter table this_table add session_binary bytea;
alter table this_table add insert_time timestamp;
alter table this_table add constraint this_table_pk primary key (key);
create index this_table_insert_time on this_table(insert_time);

These two steps are repeated on patch reinstallation, so this table was for sure dropped and recreated multiple times.

Thanks,
Alexey Makhmutov

In response to

Browse pgsql-bugs by date

  From Date Subject
Next Message Master ZX 2016-02-11 17:34:55 Re[2]: [BUGS] Re[2]: [BUGS] BUG #13869: Right Join query that never ends
Previous Message Teodor Sigaev 2016-02-11 15:36:49 Re: BUG #13440: unaccent does not remove all diacritics