BUG #16057: Faulty PK violation

From: PG Bug reporting form <noreply(at)postgresql(dot)org>
To: pgsql-bugs(at)lists(dot)postgresql(dot)org
Cc: michael(at)sageryd(dot)se
Subject: BUG #16057: Faulty PK violation
Date: 2019-10-15 07:51:11
Message-ID: 16057-8581e8a6b7133d89@postgresql.org
Views: Raw Message | Whole Thread | Download mbox | Resend email
Thread:
Lists: pgsql-bugs

The following bug has been logged on the website:

Bug reference: 16057
Logged by: Michael Sageryd
Email address: michael(at)sageryd(dot)se
PostgreSQL version: 10.6
Operating system: OSX and AWS Aurora
Description:

Both my dev environment (PG 10.6, Docker, OSX) and my prod environment (PG
10.6 AWS Aurora) has had this odd error a couple of times. I cannot reliably
reproduce it, but I have managed to force it to appear.

I have a primary key with `GENERATED BY DEFAULT AS IDENTITY `. In some odd
cases the identity counter seems to lag and I get a PK violation just by
inserting a new record. Could this be a bug related to my these two
circumstances:
- GENERATED BY DEFAULT AS IDENTITY
- DEFERRABLE INITIALLY DEFERRED

```
CREATE TABLE main.project_report_sequence (
project_id integer NOT NULL ,
report_type_id integer NOT NULL ,
sequence_id integer NOT NULL
CONSTRAINT project_report_sequence_pkey PRIMARY KEY ( project_id,
report_type_id )
);

CREATE TABLE main.sequence (
id integer GENERATED BY DEFAULT AS IDENTITY NOT NULL ,
modified_at timestamptz ,
last_value integer ,
CONSTRAINT sequence_pkey PRIMARY KEY ( id )
);

CREATE OR REPLACE FUNCTION main.tr_sequence_assert_project_sequence()
RETURNS trigger
LANGUAGE plpgsql
SECURITY DEFINER
AS $function$
BEGIN
--Asserts that the created sequence is used, i.e. being referenced from a
child table
--The only way to create a sequence is to also define it's usage in the
same transaction
--The trigger itself will be declared as DEFERRABLE INITIALLY DEFERRED to
enable creation in the same transaction
IF NOT EXISTS (SELECT 1 FROM main.project_sequence WHERE sequence_id =
NEW.id)
AND NOT EXISTS (SELECT 1 FROM main.project_report_sequence WHERE
sequence_id = NEW.id)
AND NOT EXISTS (SELECT 1 FROM main.project_report_bundle_sequence WHERE
sequence_id = NEW.id)
THEN
RAISE EXCEPTION 'Cannot create sequence (%). A sequence can only be
created together with its usage (project_sequence, project_report_sequence
or project_report_bundle_sequence ) in the same transaction', NEW.id;
ELSE
RETURN NEW;
END IF;
END;
$function$

CREATE CONSTRAINT TRIGGER ai_au__sequence__assert_project_sequence
AFTER INSERT OR UPDATE OF id ON main.sequence
DEFERRABLE INITIALLY DEFERRED FOR EACH ROW
EXECUTE PROCEDURE main.tr_sequence_assert_project_sequence();

DO
$$
DECLARE
_sequence_id int;
BEGIN
INSERT INTO main.sequence
(last_value) values (0)
RETURNING id INTO _sequence_id;

INSERT INTO main.project_report_sequence
(project_id, report_type_id, sequence_id)
VALUES (2, 2, _sequence_id);
END;$$;
```

Testing the setup with the DO-statement works in 99% of the cases. But now
and then I get a primary key violation on `sequence_pkey`. With an identity
default it should not be possible to get a PK violation. I suspect this has
to do with the deferred trigger.

As of now I can't have this setup as it's not stable. I'm also thinking that
it's overly complicated. My goal is to ensure that there are no unused
(un-referenced) records in the sequence table. I'll solve this with some
kind of periodic cleaning procedure instead.

If this is a bug, it's quite worrisome.
If I'm doing stupid things, I'll happily take some pointers.

Browse pgsql-bugs by date

  From Date Subject
Next Message PG Bug reporting form 2019-10-15 08:26:00 BUG #16058: show session_user shows a not clear error message
Previous Message Tomas Vondra 2019-10-15 07:07:25 Re: BUG #16045: vacuum_db crash and illegal memory alloc after pg_upgrade from PG11 to PG12