BUG #15968: Create table if not exists throws "relation already exists" while running in parallel transactions

From: PG Bug reporting form <noreply(at)postgresql(dot)org>
To: pgsql-bugs(at)lists(dot)postgresql(dot)org
Cc: vovik0134(at)gmail(dot)com
Subject: BUG #15968: Create table if not exists throws "relation already exists" while running in parallel transactions
Date: 2019-08-20 11:55:06
Message-ID: 15968-08549e78d5269c95@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: 15968
Logged by: Vladimir Aleshin
Email address: vovik0134(at)gmail(dot)com
PostgreSQL version: 9.6.14
Operating system: Linux
Description:

I'm using inheritance based partitioning within before insert trigger for
dynamically partition creation

Setup script:

create table base_table (
id bigint primary key,
dt timestamptz not null,
data text
);

create view base_table_v as select * from base_table;

create or replace function partition_router()
returns trigger language plpgsql security definer as
$function$
declare
v_partition_min_dt timestamptz;
v_partition_max_dt timestamptz;
v_partition_name text;
v_row base_table;
begin
if tg_op = 'UPDATE' then
raise exception 'update operation is not supported';
end if;

v_partition_min_dt := date_trunc('day', new.dt);
v_partition_max_dt := date_trunc('day', new.dt + interval '1 day');

v_partition_name := format('partition_table_%s',
to_char(v_partition_min_dt, 'YYYY_MM_DD'));

loop
begin
execute format($$
insert into %I (id, dt, data)
values ($1, $2, $3) on conflict do nothing
returning id, dt, data
$$, v_partition_name)
using new.id, new.dt, new.data
into v_row.id, v_row.dt, v_row.data;

exit;
exception when undefined_table then
execute format($$
create table if not exists %I (
id bigint primary key,
dt timestamptz null,
data text not null
check ('%s'::timestamptz <= dt and dt <
'%s'::timestamptz)
) inherits (base_table);
$$, v_partition_name, v_partition_min_dt, v_partition_max_dt);
end;
end loop;

return case when v_row.id is not null then v_row else null end;
end;
$function$;

create trigger partition_router_trg
instead of insert or update on base_table_v
for each row execute procedure partition_router();

Reproduce scenario:

Env:
$ uname -a
Linux 66eb0fb650bc 4.15.0-54-generic #58-Ubuntu SMP Mon Jun 24 10:55:24 UTC
2019 x86_64 GNU/Linux

$ psql -c "select version()"
version

--------------------------------------------------------------------------------------------------------
PostgreSQL 9.6.14 on x86_64-pc-linux-gnu (Debian 9.6.14-1.pgdg80+1),
compiled by gcc (Debian 4.9.2-10+d
eb8u2) 4.9.2, 64-bit
(1 row)

$ psql -c "show default_transaction_isolation"
default_transaction_isolation
-------------------------------
read committed
(1 row)

If there ara inserts in parallel transactions that should create new
partition on of the transactions fails with error

T1 - transaction one, T2 - transaction two

T1: postgres=# begin;
T1: BEGIN
T1: postgres=# insert into base_table_v (id, dt, data) values (1, now(),
'Hello'); NOTICE: merging column "id" with inherited definition
T1: NOTICE: merging column "dt" with inherited definition
T1: NOTICE: merging column "data" with inherited definition
T1: INSERT 0 1
T2: BEGIN
T2: postgres=# insert into base_table_v (id, dt, data) values (2, now(),
'World'); -- waits on lock
T1: postgres=# commit;
T1: COMMIT
T2: NOTICE: merging column "id" with inherited definition
T2: NOTICE: merging column "dt" with inherited definition
T2: NOTICE: merging column "data" with inherited definition
T2: ERROR: relation "partition_table_2019_08_20" already exists
T2: CONTEXT: SQL statement "
T2: create table if not exists partition_table_2019_08_20
(
T2: id bigint primary key,
T2: dt timestamptz null,
T2: data text not null
T2: check ('2019-08-20 00:00:00+03'::timestamptz <= dt
and dt < '2019-08-21 00:00:00+03'::timestamptz)
T2: ) inherits (base_table);
T2: "
T2: PL/pgSQL function partition_router() line 29 at EXECUTE

I'm using if not exists clause, so I expect that T2 should skip creation and
do insert after lock is released

Browse pgsql-bugs by date

  From Date Subject
Next Message Dave Cramer 2019-08-20 12:57:18 Re: BUG #15939: Postgres database size is growing due to oraphan objects
Previous Message Michael Paquier 2019-08-20 07:18:41 Re: BUG #15964: vacuumdb.c:187:10: error: use of undeclared identifier 'FD_SETSIZE'