1

I am building a Change Capture system that consumes the Postgres WAL through a logical decoding output plugin.

In the callbacks it is very easy to access the current transactionId (https://doxygen.postgresql.org/structReorderBufferTXN.html#ad3ff4a8f320f2ec21e3e07688d29c741) but this is the 32 bit one that can wrap around after 4B commits, thus it is not reliable as a logical counter.

Postgres internally maintains a 64 bit transactionID that does not wrap around (select txid_current()) : https://www.postgresql.org/docs/9.4/functions-info.html#FUNCTIONS-TXID-SNAPSHOT

https://github.com/postgres/postgres/blob/3412030205211079f9b0510e2244083e4ee7b15a/src/backend/access/transam/xact.c#L473-L488

Is it possible to access this ID from a logical decoding plugin? And if not, what is the reason for it?

Thanks

fpacifici
  • 523
  • 2
  • 11

1 Answers1

2

You have two options:

  1. You use OidFunctionCall0 to call the SQL function txid_current().

  2. You copy the code from txid_current, load_xid_epoch and convert_xid from src/backend/utils/adt/txid.c.

The second option will be faster, but you have to duplicate code.

Laurenz Albe
  • 209,280
  • 17
  • 206
  • 263
  • 1
    No, there are no race conditions. If as you use the function in a data modifying transaction, it won't generate a new txid, but it will return the current one. – Laurenz Albe Jun 21 '19 at 18:36
  • Thanks Laurenz, about both options, they would return the next xid (where I believe txid_current() will actually create the transaction while load_xid_epoch will not github.com/postgres/postgres/blob/…). Is it actually possible that two commits happening almost at the same time in two different processes would generate the same "next transaction id" if the two transacitons are concurrent and no new transaction starts between the first and the second commit event ? – fpacifici Jun 21 '19 at 18:41
  • sorry, I deleted the comment to reformulate the idea better before the answer came in. The original one was Lorenz responded to was: "Thanks Laurenz, about both options, they would return the next xid (where I believe txid_current() will actually create the transaction while load_xid_epoch will not github.com/postgres/postgres/blob/…). Is this going to be synchronized with the commit of the transaction I am consuming on the WAL ? Or may I run into threading problems like two commits happening almost at the same time returning the same "next xid" ?" – fpacifici Jun 21 '19 at 18:41
  • `txid_current()` will return a different `txid` when called from different transactions (otherwise PostgreSQL wouldn't work). What I'm wondering is why you need that in a logical decoding plugin. – Laurenz Albe Jun 22 '19 at 03:00