Thread: [BUGS] BUG #14639: Different xmin values in a transaction

[BUGS] BUG #14639: Different xmin values in a transaction

From
ray.warren@artsalliancemedia.com
Date:
The following bug has been logged on the website:

Bug reference:      14639
Logged by:          Ray Warren
Email address:      ray.warren@artsalliancemedia.com
PostgreSQL version: 9.5.6
Operating system:   Linux
Description:

Under certain conditions inserts in the same transaction are getting
different xmin values.
A reproducible example is below. I can work around it but I think this is a
bug.


select version();                                                version
----------------------------------------------------------------------------------------------------------PostgreSQL
9.5.6on x86_64-pc-linux-gnu, compiled by gcc (GCC) 4.8.5 
20150623 (Red Hat 4.8.5-11), 64-bit
---------------------------------------------------------------------------------------------------------
-- Create Table
---------------------------------------------------------------------------------------------------------

CREATE TABLE partition_table
( id serial NOT NULL, timestamp double precision);

---------------------------------------------------------------------------------------------------------
-- Create partition function
---------------------------------------------------------------------------------------------------------

CREATE OR REPLACE FUNCTION
partition_table_function()
RETURNS TRIGGER AS
$BODY$
DECLARE
_tablename text;
_partition_key character varying (6);
_timestamp_epoch double precision;
_start_week_timestamp timestamp;
_end_week_timestamp timestamp;
_start_week_epoch double precision;
_end_week_epoch double precision;
_result record;
BEGIN
-- Derive the partition key from the timestamp that is stored as epoch. For
this table we are using ISO Year and Week
_timestamp_epoch := NEW."timestamp";
_partition_key := to_char((to_timestamp(_timestamp_epoch) AT TIME ZONE
'UTC')::date, 'IYYYIW')::text;
-- Derive the partition name that will hold this data row
_tablename := 'partition_table_'||_partition_key;
-- Check if the partition needed for the current record exists
PERFORM 1
FROM   pg_catalog.pg_class c
JOIN   pg_catalog.pg_namespace n ON n.oid = c.relnamespace
WHERE  c.relkind = 'r'
AND    c.relname = _tablename
AND    n.nspname = 'public';

-- If the partition needed does not yet exist, then we create it:
IF NOT FOUND THEN
-- Need to find the epoch values    _start_week_timestamp :=
date_trunc('WEEK',(to_timestamp(_timestamp_epoch) AT TIME ZONE
'UTC')::date)::timestamp;   _end_week_timestamp :=
(date_trunc('WEEK',(to_timestamp(_timestamp_epoch) AT TIME ZONE
'UTC')::timestamp)::timestamp + '1 week');  _start_week_epoch := extract(epoch from _start_week_timestamp);
_end_week_epoch:= extract(epoch from _end_week_timestamp);
 
-- create the partition table   EXECUTE 'CREATE TABLE ' || quote_ident(_tablename) || ' (CHECK (
"timestamp" >= ' || quote_literal(_start_week_epoch) || ' AND "timestamp" <
'|| quote_literal(_end_week_epoch) || ')) INHERITS (partition_table)';
END IF;

-- Insert the current record into the correct partition, which we are sure
will now exist.
EXECUTE 'INSERT INTO ' || quote_ident(_tablename) || ' VALUES ($1.*)' USING
NEW;
RETURN NULL;
EXCEPTION WHEN OTHERS THEN -- Retry on conflict, now the partition should exist. EXECUTE 'INSERT INTO ' ||
quote_ident(_tablename)|| ' VALUES ($1.*)' 
USING NEW; RETURN NULL;
END;
$BODY$
LANGUAGE plpgsql;


---------------------------------------------------------------------------------------------------------
-- create trigger that calls the partition function
---------------------------------------------------------------------------------------------------------

CREATE TRIGGER partition_table_trigger
BEFORE INSERT ON partition_table
FOR EACH ROW EXECUTE PROCEDURE partition_table_function();


begin transaction;
insert into partition_table(timestamp) values (1493731429);
insert into partition_table(timestamp) values (1493731430);
insert into partition_table(timestamp) values (1493731431);
insert into partition_table(timestamp) values (1493731432);
commit;

select xmin,* from partition_table;
  xmin    | id | timestamp
-----------+----+------------528760491 |  9 | 1493731429528760492 | 10 | 1493731430528760493 | 11 | 1493731431528760494
|12 | 1493731432
 
(4 rows)xmin values should be all be the same because they are done in the same
transaction.If I comment out these 4 lines in the function--EXCEPTION WHEN OTHERS THEN-- -- Retry on conflict, now the
partitionshould exist.-- EXECUTE 'INSERT INTO ' || quote_ident(_tablename) || ' VALUES ($1.*)' 
USING NEW;-- RETURN NULL;

drop table partition_table_201718; 
begin transaction;
insert into partition_table(timestamp) values (1493731429);
insert into partition_table(timestamp) values (1493731430);
insert into partition_table(timestamp) values (1493731431);
insert into partition_table(timestamp) values (1493731432);
commit;

select xmin,* from partition_table;  xmin    | id | timestamp
-----------+----+------------528760498 | 17 | 1493731429528760498 | 18 | 1493731430528760498 | 19 | 1493731431528760498
|20 | 1493731432
 
(4 rows)

As expected all 4 rows have the same transaction id.


--
Sent via pgsql-bugs mailing list (pgsql-bugs@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-bugs

Re: [BUGS] BUG #14639: Different xmin values in a transaction

From
Andres Freund
Date:
On 2017-05-02 15:57:39 +0000, ray.warren@artsalliancemedia.com wrote:
> Under certain conditions inserts in the same transaction are getting
> different xmin values.
> A reproducible example is below. I can work around it but I think this is a
> bug.

That's to be expected if you use savepoints (and EXCEPTION blocks use
those internally).  Why do you care about xmin value?

Greetings,

Andres Freund


-- 
Sent via pgsql-bugs mailing list (pgsql-bugs@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-bugs

Re: [BUGS] BUG #14639: Different xmin values in a transaction

From
Ray Warren
Date:
Hi Andres,

I care about xmin values because we have a very high number of inserts/updates/deletes and we get a Vacuum Freeze (from
autovacuum)occurring every few days so I want to reduce that happening. The application is doing inserts in batches so
Iexpected to see batches with the same xmin. When I found they were all different I then identified what I thought was
anissue with the partition function. We can work around it but I wasn't expecting this behaviour. 

Regards ... Ray

-----Original Message-----
From: Andres Freund [mailto:andres@anarazel.de]
Sent: 02 May 2017 17:13
To: Ray Warren
Cc: pgsql-bugs@postgresql.org
Subject: Re: [BUGS] BUG #14639: Different xmin values in a transaction

On 2017-05-02 15:57:39 +0000, ray.warren@artsalliancemedia.com wrote:
> Under certain conditions inserts in the same transaction are getting
> different xmin values.
> A reproducible example is below. I can work around it but I think this
> is a bug.

That's to be expected if you use savepoints (and EXCEPTION blocks use those internally).  Why do you care about xmin
value?

Greetings,

Andres Freund



--
Sent via pgsql-bugs mailing list (pgsql-bugs@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-bugs