Hi all During the committs / replorigin split, the function to query the replication origin of a transaction from user space was lost.
A function to do so is utterly trivial, e.g. Datum pg_get_xact_replication_origin(PG_FUNCTION_ARGS) { TransactionId xid = PG_GETARG_TRANSACTIONID(0); TimestampTz ts; RepOriginId nodeid; if (TransactionIdGetCommitTsData(xid, &ts, &nodeid)) PG_RETURN_INT32((int32)nodeid); else PG_RETURN_NULL(); } ... but it probably makes more sense to extend pg_xact_commit_timestamp with support for returning the origin too. pg_xact_commit_timestamp() is a scalar function so I don't want to extend it directly because that'll upset existing callers. pg_xact_commit_timestamp_origin() (unsure if a "with" or "and" is appropriate or too long). Attached. Also add 'roident' to pg_last_committed_xact() to make the info available there too. It was already record-returning so I'm not overly concerned about adding a column. -- Craig Ringer http://www.2ndQuadrant.com/ PostgreSQL Development, 24x7 Support, Training & Services
From e022ad7168936800fb18f397e7f42538871e27d3 Mon Sep 17 00:00:00 2001 From: Craig Ringer <cr...@2ndquadrant.com> Date: Mon, 26 Mar 2018 16:23:59 +0800 Subject: [PATCH v1] Add pg_xact_commit_timestamp_origin() Add an extended version of pg_xact_commit_timestamp(), called pg_xact_commit_timestamp_origin(), that returns the replication origin as well as the commit timestamp. It's done this way rather than as a wholly separate function because replication origin information is tracked alongside commit timestamps, and it's significantly more efficient to fetch both at once. Also extend pg_last_committed_xact() with a roident column with the replication origin of the last committed transaction. --- doc/src/sgml/func.sgml | 17 +++++-- src/backend/access/transam/commit_ts.c | 59 +++++++++++++++++++--- src/include/catalog/pg_proc.h | 5 +- src/test/modules/commit_ts/commit_ts.conf | 2 +- .../commit_ts/expected/commit_timestamp.out | 49 ++++++++++++++++-- .../commit_ts/expected/commit_timestamp_1.out | 34 ++++++++++++- .../modules/commit_ts/sql/commit_timestamp.sql | 14 ++++- 7 files changed, 162 insertions(+), 18 deletions(-) diff --git a/doc/src/sgml/func.sgml b/doc/src/sgml/func.sgml index 7b1a85fc71..dae5fef6c8 100644 --- a/doc/src/sgml/func.sgml +++ b/doc/src/sgml/func.sgml @@ -17928,7 +17928,9 @@ SELECT collation for ('foo' COLLATE "de_DE"); These functions mainly provide information about when the transactions were committed. They only provide useful data when <xref linkend="guc-track-commit-timestamp"/> configuration option is enabled - and only for transactions that were committed after it was enabled. + and only for transactions that were committed after it was enabled. The reported + replication origin information is maintained by the <link linkend="replication-origins"> + replication origins</link> subsystem. </para> <table id="functions-commit-timestamp"> @@ -17948,13 +17950,22 @@ SELECT collation for ('foo' COLLATE "de_DE"); <entry>get commit timestamp of a transaction</entry> </row> + <row> + <entry> + <indexterm><primary>pg_xact_commit_timestamp_origin</primary></indexterm> + <literal><function>pg_xact_commit_timestamp_origin(<parameter>xid</parameter>)</function></literal> + </entry> + <entry><parameter>timestamp</parameter> <type>timestamptz</type>, <parameter>roident</parameter> <type>oid</type></entry> + <entry>get commit timestamp and replication origin of a transaction</entry> + </row> + <row> <entry> <indexterm><primary>pg_last_committed_xact</primary></indexterm> <literal><function>pg_last_committed_xact()</function></literal> </entry> - <entry><parameter>xid</parameter> <type>xid</type>, <parameter>timestamp</parameter> <type>timestamp with time zone</type></entry> - <entry>get transaction ID and commit timestamp of latest committed transaction</entry> + <entry><parameter>xid</parameter> <type>xid</type>, <parameter>timestamp</parameter> <type>timestamp with time zone</type>, <parameter>roident</parameter> <type>oid</type></entry> + <entry>get transaction ID, commit timestamp and replication origin of latest committed transaction</entry> </row> </tbody> </tgroup> diff --git a/src/backend/access/transam/commit_ts.c b/src/backend/access/transam/commit_ts.c index 04a15e4e29..73d4ac0a9c 100644 --- a/src/backend/access/transam/commit_ts.c +++ b/src/backend/access/transam/commit_ts.c @@ -416,29 +416,73 @@ pg_xact_commit_timestamp(PG_FUNCTION_ARGS) PG_RETURN_TIMESTAMPTZ(ts); } - Datum -pg_last_committed_xact(PG_FUNCTION_ARGS) +pg_xact_commit_timestamp_origin(PG_FUNCTION_ARGS) { - TransactionId xid; + TransactionId xid = PG_GETARG_UINT32(0); TimestampTz ts; + RepOriginId origin; + bool found; + TupleDesc tupdesc; Datum values[2]; - bool nulls[2]; + bool nulls[2] = {false, false}; + HeapTuple tup; + + /* + * Construct a tuple descriptor for the result row. This must match this + * function's pg_proc entry! + */ + tupdesc = CreateTemplateTupleDesc(2, false); + TupleDescInitEntry(tupdesc, (AttrNumber) 1, "timestamp", + TIMESTAMPTZOID, -1, 0); + TupleDescInitEntry(tupdesc, (AttrNumber) 2, "roident", + OIDOID, -1, 0); + tupdesc = BlessTupleDesc(tupdesc); + + found = TransactionIdGetCommitTsData(xid, &ts, &origin); + + if (found) + { + values[0] = TimestampTzGetDatum(ts); + values[1] = ObjectIdGetDatum(origin); + } + else + { + values[0] = (Datum)0; + nulls[0] = true; + values[1] = (Datum)0; + nulls[1] = true; + } + + tup = heap_form_tuple(tupdesc, values, nulls); + PG_RETURN_DATUM(HeapTupleGetDatum(tup)); +} + +Datum +pg_last_committed_xact(PG_FUNCTION_ARGS) +{ + TransactionId xid; + TimestampTz ts; + Datum values[3]; + bool nulls[3]; TupleDesc tupdesc; HeapTuple htup; + RepOriginId origin; /* and construct a tuple with our data */ - xid = GetLatestCommitTsData(&ts, NULL); + xid = GetLatestCommitTsData(&ts, &origin); /* * Construct a tuple descriptor for the result row. This must match this * function's pg_proc entry! */ - tupdesc = CreateTemplateTupleDesc(2, false); + tupdesc = CreateTemplateTupleDesc(3, false); TupleDescInitEntry(tupdesc, (AttrNumber) 1, "xid", XIDOID, -1, 0); TupleDescInitEntry(tupdesc, (AttrNumber) 2, "timestamp", TIMESTAMPTZOID, -1, 0); + TupleDescInitEntry(tupdesc, (AttrNumber) 3, "roident", + OIDOID, -1, 0); tupdesc = BlessTupleDesc(tupdesc); if (!TransactionIdIsNormal(xid)) @@ -452,6 +496,9 @@ pg_last_committed_xact(PG_FUNCTION_ARGS) values[1] = TimestampTzGetDatum(ts); nulls[1] = false; + + values[2] = ObjectIdGetDatum(origin); + nulls[2] = false; } htup = heap_form_tuple(tupdesc, values, nulls); diff --git a/src/include/catalog/pg_proc.h b/src/include/catalog/pg_proc.h index bfc90098f8..b6220efa75 100644 --- a/src/include/catalog/pg_proc.h +++ b/src/include/catalog/pg_proc.h @@ -3237,7 +3237,10 @@ DESCR("view members of a multixactid"); DATA(insert OID = 3581 ( pg_xact_commit_timestamp PGNSP PGUID 12 1 0 0 0 f f f t f v s 1 0 1184 "28" _null_ _null_ _null_ _null_ _null_ pg_xact_commit_timestamp _null_ _null_ _null_ )); DESCR("get commit timestamp of a transaction"); -DATA(insert OID = 3583 ( pg_last_committed_xact PGNSP PGUID 12 1 0 0 0 f f f t f v s 0 0 2249 "" "{28,1184}" "{o,o}" "{xid,timestamp}" _null_ _null_ pg_last_committed_xact _null_ _null_ _null_ )); +DATA(insert OID = 3423 ( pg_xact_commit_timestamp_origin PGNSP PGUID 12 1 0 0 0 f f f t f v s 1 0 2249 "28" "{28,1184,26}" "{i,o,o}" "{xid,timestamp,roident}" _null_ _null_ pg_xact_commit_timestamp_origin _null_ _null_ _null_ )); +DESCR("get commit timestamp and replication origin of a transaction"); + +DATA(insert OID = 3583 ( pg_last_committed_xact PGNSP PGUID 12 1 0 0 0 f f f t f v s 0 0 2249 "" "{28,1184,26}" "{o,o,o}" "{xid,timestamp,roident}" _null_ _null_ pg_last_committed_xact _null_ _null_ _null_ )); DESCR("get transaction Id and commit timestamp of latest transaction commit"); DATA(insert OID = 3537 ( pg_describe_object PGNSP PGUID 12 1 0 0 0 f f f t f s s 3 0 25 "26 26 23" _null_ _null_ _null_ _null_ _null_ pg_describe_object _null_ _null_ _null_ )); diff --git a/src/test/modules/commit_ts/commit_ts.conf b/src/test/modules/commit_ts/commit_ts.conf index e9d3c35756..ddd13213ad 100644 --- a/src/test/modules/commit_ts/commit_ts.conf +++ b/src/test/modules/commit_ts/commit_ts.conf @@ -1 +1 @@ -track_commit_timestamp = on +track_commit_timestamp = off diff --git a/src/test/modules/commit_ts/expected/commit_timestamp.out b/src/test/modules/commit_ts/expected/commit_timestamp.out index 5b7783b58f..048b1af7da 100644 --- a/src/test/modules/commit_ts/expected/commit_timestamp.out +++ b/src/test/modules/commit_ts/expected/commit_timestamp.out @@ -11,6 +11,33 @@ CREATE TABLE committs_test(id serial, ts timestamptz default now()); INSERT INTO committs_test DEFAULT VALUES; INSERT INTO committs_test DEFAULT VALUES; INSERT INTO committs_test DEFAULT VALUES; +SELECT pg_replication_origin_create('test_origin'); + pg_replication_origin_create +------------------------------ + 1 +(1 row) + +SELECT pg_replication_origin_session_setup('test_origin'); + pg_replication_origin_session_setup +------------------------------------- + +(1 row) + +BEGIN; +SELECT pg_replication_origin_xact_setup('1/1', '1990-01-01'); + pg_replication_origin_xact_setup +---------------------------------- + +(1 row) + +INSERT INTO committs_test DEFAULT VALUES; +COMMIT; +SELECT pg_replication_origin_session_reset(); + pg_replication_origin_session_reset +------------------------------------- + +(1 row) + SELECT id, pg_xact_commit_timestamp(xmin) >= ts, pg_xact_commit_timestamp(xmin) <= now(), @@ -22,7 +49,19 @@ ORDER BY id; 1 | t | t | t 2 | t | t | t 3 | t | t | t -(3 rows) + 4 | f | t | t +(4 rows) + +SELECT roident = 0, roident = 1 +FROM committs_test, pg_xact_commit_timestamp_origin(xmin) +ORDER BY id; + ?column? | ?column? +----------+---------- + t | f + t | f + t | f + f | t +(4 rows) DROP TABLE committs_test; SELECT pg_xact_commit_timestamp('0'::xid); @@ -39,9 +78,9 @@ SELECT pg_xact_commit_timestamp('2'::xid); (1 row) -SELECT x.xid::text::bigint > 0, x.timestamp > '-infinity'::timestamptz, x.timestamp <= now() FROM pg_last_committed_xact() x; - ?column? | ?column? | ?column? -----------+----------+---------- - t | t | t +SELECT x.xid::text::bigint > 0, x.timestamp > '-infinity'::timestamptz, x.timestamp <= now(), roident = 0 FROM pg_last_committed_xact() x; + ?column? | ?column? | ?column? | ?column? +----------+----------+----------+---------- + t | t | t | t (1 row) diff --git a/src/test/modules/commit_ts/expected/commit_timestamp_1.out b/src/test/modules/commit_ts/expected/commit_timestamp_1.out index c10b0abc2b..2546a46441 100644 --- a/src/test/modules/commit_ts/expected/commit_timestamp_1.out +++ b/src/test/modules/commit_ts/expected/commit_timestamp_1.out @@ -11,6 +11,33 @@ CREATE TABLE committs_test(id serial, ts timestamptz default now()); INSERT INTO committs_test DEFAULT VALUES; INSERT INTO committs_test DEFAULT VALUES; INSERT INTO committs_test DEFAULT VALUES; +SELECT pg_replication_origin_create('test_origin'); + pg_replication_origin_create +------------------------------ + 1 +(1 row) + +SELECT pg_replication_origin_session_setup('test_origin'); + pg_replication_origin_session_setup +------------------------------------- + +(1 row) + +BEGIN; +SELECT pg_replication_origin_xact_setup('1/1', '1990-01-01'); + pg_replication_origin_xact_setup +---------------------------------- + +(1 row) + +INSERT INTO committs_test DEFAULT VALUES; +COMMIT; +SELECT pg_replication_origin_session_reset(); + pg_replication_origin_session_reset +------------------------------------- + +(1 row) + SELECT id, pg_xact_commit_timestamp(xmin) >= ts, pg_xact_commit_timestamp(xmin) <= now(), @@ -19,6 +46,11 @@ FROM committs_test ORDER BY id; ERROR: could not get commit timestamp data HINT: Make sure the configuration parameter "track_commit_timestamp" is set. +SELECT roident = 0, roident = 1 +FROM committs_test, pg_xact_commit_timestamp_origin(xmin) +ORDER BY id; +ERROR: could not get commit timestamp data +HINT: Make sure the configuration parameter "track_commit_timestamp" is set. DROP TABLE committs_test; SELECT pg_xact_commit_timestamp('0'::xid); ERROR: cannot retrieve commit timestamp for transaction 0 @@ -34,6 +66,6 @@ SELECT pg_xact_commit_timestamp('2'::xid); (1 row) -SELECT x.xid::text::bigint > 0, x.timestamp > '-infinity'::timestamptz, x.timestamp <= now() FROM pg_last_committed_xact() x; +SELECT x.xid::text::bigint > 0, x.timestamp > '-infinity'::timestamptz, x.timestamp <= now(), roident = 0 FROM pg_last_committed_xact() x; ERROR: could not get commit timestamp data HINT: Make sure the configuration parameter "track_commit_timestamp" is set. diff --git a/src/test/modules/commit_ts/sql/commit_timestamp.sql b/src/test/modules/commit_ts/sql/commit_timestamp.sql index 4e041a5347..896f7ea6bd 100644 --- a/src/test/modules/commit_ts/sql/commit_timestamp.sql +++ b/src/test/modules/commit_ts/sql/commit_timestamp.sql @@ -8,6 +8,14 @@ INSERT INTO committs_test DEFAULT VALUES; INSERT INTO committs_test DEFAULT VALUES; INSERT INTO committs_test DEFAULT VALUES; +SELECT pg_replication_origin_create('test_origin'); +SELECT pg_replication_origin_session_setup('test_origin'); +BEGIN; +SELECT pg_replication_origin_xact_setup('1/1', '1990-01-01'); +INSERT INTO committs_test DEFAULT VALUES; +COMMIT; +SELECT pg_replication_origin_session_reset(); + SELECT id, pg_xact_commit_timestamp(xmin) >= ts, pg_xact_commit_timestamp(xmin) <= now(), @@ -15,10 +23,14 @@ SELECT id, FROM committs_test ORDER BY id; +SELECT roident = 0, roident = 1 +FROM committs_test, pg_xact_commit_timestamp_origin(xmin) +ORDER BY id; + DROP TABLE committs_test; SELECT pg_xact_commit_timestamp('0'::xid); SELECT pg_xact_commit_timestamp('1'::xid); SELECT pg_xact_commit_timestamp('2'::xid); -SELECT x.xid::text::bigint > 0, x.timestamp > '-infinity'::timestamptz, x.timestamp <= now() FROM pg_last_committed_xact() x; +SELECT x.xid::text::bigint > 0, x.timestamp > '-infinity'::timestamptz, x.timestamp <= now(), roident = 0 FROM pg_last_committed_xact() x; -- 2.14.3