Обсуждение: [PATCH] Add pg_current_vxact_id() function to expose virtual transaction IDs

Поиск
Список
Период
Сортировка

[PATCH] Add pg_current_vxact_id() function to expose virtual transaction IDs

От
"Pavlo Golub"
Дата:
Hi hackers,

I'd like to propose a new function pg_current_vxact_id() that returns
the
current backend's virtual transaction ID (VXID).

Virtual transaction IDs are fundamental to PostgreSQL's transaction
tracking,
appearing in pg_locks.virtualtransaction, log output via %v placeholder,
and
internal transaction management. However, there's currently no direct
SQL
function to retrieve the current VXID, forcing applications to query
pg_locks
or parse log files to obtain this information.

The patch adds pg_current_vxact_id() which returns the VXID as text in
the
format "procNumber/lxid" (e.g., "3/42"), matching the format used
throughout
PostgreSQL for consistency.

Use cases:
1. Application transaction tracking and correlation with logs
2. Monitoring read-only transactions (which never get regular XIDs)
3. Debugging transaction behavior without querying pg_locks
4. Building monitoring tools that need consistent transaction identity

The function follows the same pattern as pg_current_xact_id() and
pg_current_xact_id_if_assigned(), providing a clean API for a commonly
needed piece of information.

Changes:
- Added function in xid8funcs.c (alongside related transaction ID
functions)
- OID 5101 (verified available with unused_oids script)
- Comprehensive regression tests in xid.sql
- Documentation in func-info.sgml and xact.sgml
- Format kept in sync with existing VXID representations in elog.c and
lockfuncs.c

The v1 patch is attached. Tests pass cleanly with "meson test
regress/regress".

Best regards,
Pavlo Golub

Вложения

Re: [PATCH] Add pg_current_vxact_id() function to expose virtual transaction IDs

От
Henson Choi
Дата:
I looked into where VXID is actually used:

  SELECT c.relname, a.attname 
  FROM pg_attribute a JOIN pg_class c ON a.attrelid = c.oid 
  WHERE a.attname LIKE '%virtual%' AND a.attnum > 0;

   relname  |      attname       
  ----------+--------------------
   pg_locks | virtualxid
   pg_locks | virtualtransaction

Only pg_locks has it. And you can already get your VXID from there:

  SELECT virtualtransaction FROM pg_locks 
  WHERE pid = pg_backend_pid() LIMIT 1;

This always works since every transaction holds its own VXID lock.

For log correlation, PID works in most cases.

So I'm having trouble seeing a compelling use case. Could you share
a concrete scenario where this function would help?

The patch itself is clean, but I'm not sure about the justification.

Re: [PATCH] Add pg_current_vxact_id() function to expose virtual transaction IDs

От
Henson Choi
Дата:
I looked into where VXID is actually used:

  SELECT c.relname, a.attname 
  FROM pg_attribute a JOIN pg_class c ON a.attrelid = c.oid 
  WHERE a.attname LIKE '%virtual%' AND a.attnum > 0;

   relname  |      attname       
  ----------+--------------------
   pg_locks | virtualxid
   pg_locks | virtualtransaction

Only pg_locks has it. And you can already get your VXID from there:

  SELECT virtualtransaction FROM pg_locks 
  WHERE pid = pg_backend_pid() LIMIT 1;

This always works since every transaction holds its own VXID lock.

For log correlation, PID works in most cases.

So I'm having trouble seeing a compelling use case. Could you share
a concrete scenario where this function would help?

The patch itself is clean, but I'm not sure about the justification.

2025년 12월 8일 (월) PM 9:10, Pavlo Golub <pavlo.golub@cybertec.at>님이 작성:
Hi hackers,

I'd like to propose a new function pg_current_vxact_id() that returns
the
current backend's virtual transaction ID (VXID).

Virtual transaction IDs are fundamental to PostgreSQL's transaction
tracking,
appearing in pg_locks.virtualtransaction, log output via %v placeholder,
and
internal transaction management. However, there's currently no direct
SQL
function to retrieve the current VXID, forcing applications to query
pg_locks
or parse log files to obtain this information.

The patch adds pg_current_vxact_id() which returns the VXID as text in
the
format "procNumber/lxid" (e.g., "3/42"), matching the format used
throughout
PostgreSQL for consistency.

Use cases:
1. Application transaction tracking and correlation with logs
2. Monitoring read-only transactions (which never get regular XIDs)
3. Debugging transaction behavior without querying pg_locks
4. Building monitoring tools that need consistent transaction identity

The function follows the same pattern as pg_current_xact_id() and
pg_current_xact_id_if_assigned(), providing a clean API for a commonly
needed piece of information.

Changes:
- Added function in xid8funcs.c (alongside related transaction ID
functions)
- OID 5101 (verified available with unused_oids script)
- Comprehensive regression tests in xid.sql
- Documentation in func-info.sgml and xact.sgml
- Format kept in sync with existing VXID representations in elog.c and
lockfuncs.c

The v1 patch is attached. Tests pass cleanly with "meson test
regress/regress".

Best regards,
Pavlo Golub

Re: [PATCH] Add pg_current_vxact_id() function to expose virtual transaction IDs

От
Michael Paquier
Дата:
On Mon, Dec 08, 2025 at 12:09:58PM +0000, Pavlo Golub wrote:
> Changes:
> - OID 5101 (verified available with unused_oids script)

./unused_oids also states the following thing:
Best practice is to start with a random choice in the range 8000-9999.

We do an OID renumbering while in beta, so please use an OID in this
range for the development of new patches.  ;)
--
Michael

Вложения

Re[2]: [PATCH] Add pg_current_vxact_id() function to expose virtual transaction IDs

От
"Pavlo Golub"
Дата:
Greetings!
>>  Changes:
>>  - OID 5101 (verified available with unused_oids script)
>
>./unused_oids also states the following thing:
>Best practice is to start with a random choice in the range 8000-9999.

Oh, I misunderstood it completely. I thought one should go to 8K+ if
they
want a block of OIDs not just one. Thanks!
>
>
>We do an OID renumbering while in beta, so please use an OID in this
>range for the development of new patches.  ;)

Cool! Will update the patch. Thanks for your input!

Best regards,
Pavlo



Re[2]: [PATCH] Add pg_current_vxact_id() function to expose virtual transaction IDs

От
"Pavlo Golub"
Дата:
Hello.

Attached is v2 of the pg_current_vxact_id() patch.
Changes in v2:
- Rebased on current master
- Changed OID from 5101 to 9538 (following unused_oids best practice
   recommendation to use the 8000-9999 range for patch development)

Best regards,
Pavlo Golub
Вложения

Re[2]: [PATCH] Add pg_current_vxact_id() function to expose virtual transaction IDs

От
"Pavlo Golub"
Дата:
Hello.

Thanks for the review.

>
>Only pg_locks has it. And you can already get your VXID from there:
>
>   SELECT virtualtransaction FROM pg_locks
>   WHERE pid = pg_backend_pid() LIMIT 1;
While it is true that pg_locks contains the virtual transaction
information, I believe there are strong technical reasons to expose this
directly via a function.
First of all, querying pg_locks is expensive. By contrast,
pg_current_vxact_id() is a practically free O(1) read from MyProc.
The %v log placeholder is the specific identifier for individual
transaction executions (including read-only ones where no permanent XID
is assigned). PIDs (%p) are session-scoped and too coarse for helping
debug specific transactions in connection-pooled environments. This
function allows applications to easily obtain the ID needed to correlate
with server logs.
We already provide fast accessors for other identifiers like
pg_backend_pid() and pg_current_xact_id(). Additionally, PostgreSQL
often provides utility functions that overlap with other commands or
views to improve developer experience (e.g., pg_notify() vs NOTIFY,
pg_sleep() vs pg_sleep_for() vs pg_sleep_until()). It feels consistent
to offer a simple accessor rather than requiring a complex query against
a system view.

Best regards,
Pavlo Golub




Hi Pavlo,

Thank you for the v2 patch. I've reviewed it and here are my comments:

== Summary ==

The patch applies cleanly and all regression tests pass.
The implementation is straightforward and follows existing patterns.

== Detailed Review ==

1. Functionality: OK
   - The function correctly returns the VXID in the expected format.

2. Tests: OK
   - Regression tests are included and pass.
   - gcov/valgrind testing is unnecessary due to the simplicity of the code.

3. Code Safety: OK
   - Buffer size (32 bytes) is sufficient for maximum output (23 bytes),
     consistent with VXIDGetDatum() in lockfuncs.c.
   - Memory allocated by cstring_to_text() via palloc is in
     ecxt_per_tuple_memory and automatically managed.

4. Typos: None found.

== Suggestions for Improvement ==

1. Format String Duplication

   The format string "%d/%u" is now duplicated in three places:
   - src/backend/utils/adt/lockfuncs.c (VXIDGetDatum)
   - src/backend/utils/error/elog.c (%v placeholder)
   - src/backend/utils/adt/xid8funcs.c (pg_current_vxact_id)

   Consider defining a macro in lock.h for consistency:

     #define VXID_FMT "%d/%u"

   All three files already include lock.h indirectly:
   - lockfuncs.c -> predicate_internals.h -> lock.h
   - elog.c -> proc.h -> lock.h
   - xid8funcs.c -> proc.h -> lock.h

2. Documentation Terminology

   The terms "localTransactionId" and "localXID" are used inconsistently:
   - localTransactionId: 30+ in C code (actual field name), 1 in sgml (monitoring.sgml)
   - localXID: 3 in sgml only (xact.sgml, config.sgml)

   The new func-info.sgml uses "localTransactionId" which matches the
   actual C struct field name. However, existing documentation prefers
   "localXID" for user-facing text. Consider using "localXID" in
   func-info.sgml for consistency with xact.sgml and config.sgml.

== Comparison with pg_current_xact_id ==

The implementation follows a similar pattern to pg_current_xact_id(),
which was introduced in commit 4c04be9b05a. The placement in
xid8funcs.c is appropriate.

--

2026년 1월 6일 (화) PM 9:47, Pavlo Golub <pavlo.golub@cybertec.at>님이 작성:
Hello.

Attached is v2 of the pg_current_vxact_id() patch.
Changes in v2:
- Rebased on current master
- Changed OID from 5101 to 9538 (following unused_oids best practice
   recommendation to use the 8000-9999 range for patch development)

Best regards,
Pavlo Golub

Best regards,
Henson
 
Hi Pavlo,

2026년 1월 6일 (화) PM 10:32, Pavlo Golub <pavlo.golub@cybertec.at>님이 작성:
Hello.

Thanks for the review.

>
>Only pg_locks has it. And you can already get your VXID from there:
>
>   SELECT virtualtransaction FROM pg_locks
>   WHERE pid = pg_backend_pid() LIMIT 1;
While it is true that pg_locks contains the virtual transaction
information, I believe there are strong technical reasons to expose this
directly via a function.

Agreed.
 
First of all, querying pg_locks is expensive. By contrast,
pg_current_vxact_id() is a practically free O(1) read from MyProc.

Yes, this is a significant advantage. The function simply reads from
MyProc without any locking or iteration.
  
The %v log placeholder is the specific identifier for individual
transaction executions (including read-only ones where no permanent XID
is assigned). PIDs (%p) are session-scoped and too coarse for helping
debug specific transactions in connection-pooled environments. This
function allows applications to easily obtain the ID needed to correlate
with server logs.

This is a compelling use case. In connection-pooled environments,
correlating application-side logs with server logs by VXID is much
more precise than using PIDs.
 
We already provide fast accessors for other identifiers like
pg_backend_pid() and pg_current_xact_id(). Additionally, PostgreSQL
often provides utility functions that overlap with other commands or
views to improve developer experience (e.g., pg_notify() vs NOTIFY,
pg_sleep() vs pg_sleep_for() vs pg_sleep_until()). It feels consistent
to offer a simple accessor rather than requiring a complex query against
a system view.


I agree. This follows established PostgreSQL patterns.
 
Best regards,
Pavlo Golub


Additionally, the implementation is minimal (~20 lines), so the binary
size impact is negligible. And since it's a leaf function called only
when explicitly invoked by users, it has no impact on the main code
path performance.
 
Best regards,
Henson 
Hi Pavlo,

I've moved this patch to "Waiting on author" status in the commitfest.

I'm interested in your thoughts on the two suggestions from my review:

1. VXID_FMT macro to eliminate format string duplication
2. Using "localXID" terminology in documentation for consistency

Would you like to incorporate these in v3, or do you have concerns
about either suggestion?

Looking forward to your feedback.

Best regards,
Henson Choi

2026년 1월 6일 (화) PM 10:59, Henson Choi <assam258@gmail.com>님이 작성:
Hi Pavlo,

Thank you for the v2 patch. I've reviewed it and here are my comments:

== Summary ==

The patch applies cleanly and all regression tests pass.
The implementation is straightforward and follows existing patterns.

== Detailed Review ==

1. Functionality: OK
   - The function correctly returns the VXID in the expected format.

2. Tests: OK
   - Regression tests are included and pass.
   - gcov/valgrind testing is unnecessary due to the simplicity of the code.

3. Code Safety: OK
   - Buffer size (32 bytes) is sufficient for maximum output (23 bytes),
     consistent with VXIDGetDatum() in lockfuncs.c.
   - Memory allocated by cstring_to_text() via palloc is in
     ecxt_per_tuple_memory and automatically managed.

4. Typos: None found.

== Suggestions for Improvement ==

1. Format String Duplication

   The format string "%d/%u" is now duplicated in three places:
   - src/backend/utils/adt/lockfuncs.c (VXIDGetDatum)
   - src/backend/utils/error/elog.c (%v placeholder)
   - src/backend/utils/adt/xid8funcs.c (pg_current_vxact_id)

   Consider defining a macro in lock.h for consistency:

     #define VXID_FMT "%d/%u"

   All three files already include lock.h indirectly:
   - lockfuncs.c -> predicate_internals.h -> lock.h
   - elog.c -> proc.h -> lock.h
   - xid8funcs.c -> proc.h -> lock.h

2. Documentation Terminology

   The terms "localTransactionId" and "localXID" are used inconsistently:
   - localTransactionId: 30+ in C code (actual field name), 1 in sgml (monitoring.sgml)
   - localXID: 3 in sgml only (xact.sgml, config.sgml)

   The new func-info.sgml uses "localTransactionId" which matches the
   actual C struct field name. However, existing documentation prefers
   "localXID" for user-facing text. Consider using "localXID" in
   func-info.sgml for consistency with xact.sgml and config.sgml.

== Comparison with pg_current_xact_id ==

The implementation follows a similar pattern to pg_current_xact_id(),
which was introduced in commit 4c04be9b05a. The placement in
xid8funcs.c is appropriate.

--

2026년 1월 6일 (화) PM 9:47, Pavlo Golub <pavlo.golub@cybertec.at>님이 작성:
Hello.

Attached is v2 of the pg_current_vxact_id() patch.
Changes in v2:
- Rebased on current master
- Changed OID from 5101 to 9538 (following unused_oids best practice
   recommendation to use the 8000-9999 range for patch development)

Best regards,
Pavlo Golub

Best regards,
Henson
 

Re: [PATCH] Add pg_current_vxact_id() function to expose virtual transaction IDs

От
Michael Paquier
Дата:
On Mon, Dec 08, 2025 at 12:09:58PM +0000, Pavlo Golub wrote:
> Virtual transaction IDs are fundamental to PostgreSQL's transaction
> tracking,
> appearing in pg_locks.virtualtransaction, log output via %v placeholder, and
> internal transaction management. However, there's currently no direct SQL
> function to retrieve the current VXID, forcing applications to query
> pg_locks
> or parse log files to obtain this information.

This is replacing one SQL in a given session by another, as a session
currently running a transaction can query itself pg_locks and match an
entry with its own pg_backend_pid().  Hence I don't see the need for
this function, except simplicity in retrieving a session's state with
less characters typed at the end?

Thoughts and opinions from others are welcome.  I'm always OK to be
outvoted.
--
Michael

Вложения

Re: [PATCH] Add pg_current_vxact_id() function to expose virtual transaction IDs

От
Henson Choi
Дата:


2026년 1월 9일 (금) AM 9:25, Michael Paquier <michael@paquier.xyz>님이 작성:
On Mon, Dec 08, 2025 at 12:09:58PM +0000, Pavlo Golub wrote:
> Virtual transaction IDs are fundamental to PostgreSQL's transaction
> tracking,
> appearing in pg_locks.virtualtransaction, log output via %v placeholder, and
> internal transaction management. However, there's currently no direct SQL
> function to retrieve the current VXID, forcing applications to query
> pg_locks
> or parse log files to obtain this information.

This is replacing one SQL in a given session by another, as a session
currently running a transaction can query itself pg_locks and match an
entry with its own pg_backend_pid().  Hence I don't see the need for
this function, except simplicity in retrieving a session's state with
less characters typed at the end?

I see this as a tradeoff between minor convenience and negligible
addition cost.

The community should decide whether this tradeoff is worth it.


Thoughts and opinions from others are welcome.  I'm always OK to be
outvoted.
--
Michael

Best regards,
Henson Choi