| From: | Pavlo Golub <pavlo(dot)golub(at)cybertec(dot)at> |
|---|---|
| To: | Robert Haas <robertmhaas(at)gmail(dot)com> |
| Cc: | assam258(at)gmail(dot)com, Michael Paquier <michael(at)paquier(dot)xyz>, pgsql-hackers(at)lists(dot)postgresql(dot)org |
| Subject: | [PATCH v4] Add pg_current_vxact_id() function |
| Date: | 2026-08-21 15:42:26 |
| Message-ID: | CAK7ymcJLdpeHLiXZQj0OzAar3cgpWdXDU=uDqYLYsaHbrDZj2A@mail.gmail.com |
| Views: | Whole Thread | Raw Message | Download mbox | Resend email |
| Thread: | |
| Lists: | pgsql-hackers |
Hi hackers,
Attached is v4 of the patch adding a pg_current_vxact_id() function to
PostgreSQL. Also please find thorough performance test results as Robert
requested.
Changes in v4:
- Rebased onto current master (no functional changes)
- Addresses review comments from Henson Choi
== What the patch does ==
This patch introduces pg_current_vxact_id(), which exposes the current
backend's virtual transaction ID (VXID) as text in the format
'procNumber/localXID' (e.g., '3/42').
Virtual transaction IDs are always assigned to every backend, unlike
regular XIDs which are only assigned when a transaction modifies data.
This makes VXIDs useful for tracking and correlating all transactions,
including read-only ones, without consuming XID space.
The VXID format matches what is already used in:
- the %v placeholder in elog/log output
- the pg_locks.virtualtransaction column
- internal PostgreSQL transaction tracking
The function returns NULL during recovery or when no valid VXID exists.
== Performance ==
The existing workaround for getting one's own VXID is a scan of pg_locks:
SELECT virtualtransaction FROM pg_locks
WHERE pid = pg_backend_pid() AND locktype = 'virtualxid' LIMIT 1;
pg_locks scans the entire shared lock table (under LWLocks), so its cost
grows with the number of locks held system-wide. pg_current_vxact_id()
reads a single field from MyProc — O(1) with no lock acquisition.
Measured with pgbench on Linux x86-64, 16 CPUs (PostgreSQL 20devel).
Each run is 10 seconds; tps = transactions per second (higher is better).
Setup:
CREATE TABLE locktest (id int PRIMARY KEY, val text);
INSERT INTO locktest SELECT i, 'x' FROM generate_series(1, 10000) i;
pgbench scripts:
-- workaround (bench_pglocks.sql)
SELECT virtualtransaction FROM pg_locks
WHERE pid = pg_backend_pid() AND locktype = 'virtualxid' LIMIT 1;
-- new function (bench_vxact.sql)
SELECT pg_current_vxact_id();
Command:
pgbench -f bench_pglocks.sql -T 10 -c <N> -j <N> postgres
pgbench -f bench_vxact.sql -T 10 -c <N> -j <N> postgres
For the "with locks" scenario, 50 background sessions were opened each
holding an explicit transaction with SELECT ... FOR UPDATE on 200 rows
(keeping those transactions open for the duration of the benchmark run).
Baseline -- no extra locks held system-wide:
clients pg_locks workaround pg_current_vxact_id() speedup
1 5,991 tps 12,051 tps ~2x
8 37,221 tps 74,990 tps ~2x
16 82,132 tps 585,762 tps ~7x
With 50 background sessions each holding 200 row-locks (~10,000 locks
system-wide):
clients pg_locks workaround pg_current_vxact_id() speedup
1 4,559 tps 11,759 tps ~2.6x
8 28,338 tps 74,855 tps ~2.6x
16 51,893 tps 534,876 tps ~10x
The pg_locks workaround drops 24% at c=1 and 37% at c=16 as lock count
grows; pg_current_vxact_id() is unaffected (O(1), no LWLock). The gap
widens further with more clients due to LWLock contention on the shared
lock table.
== Why this approach ==
Rather than adding a new type, the function returns text in the canonical
'procNumber/localXID' format already established by pg_locks, so callers
can join directly against pg_locks.virtualtransaction without any casting.
A VXID_FMT macro was added to lock.h to eliminate the format-string
duplication that existed across lockfuncs.c, elog.c, and xid8funcs.c.
== Status ==
The patch compiles cleanly on Linux x86-64 and passes the full regression
test suite (make check). Regression tests covering the new function are
included in src/test/regress/sql/xid.sql. Documentation is in
func-info.sgml and xact.sgml.
Prior discussion:
Patch attached.
Regards,
Pavlo Golub
CYBERTEC PostgreSQL International GmbH
| Attachment | Content-Type | Size |
|---|---|---|
| v4-0001-Add-pg_current_vxact_id-function.patch | application/octet-stream | 9.6 KB |
| From | Date | Subject | |
|---|---|---|---|
| Next Message | Pavel Stehule | 2026-08-21 15:47:49 | Re: toast table corrupted by vacuum - missing chunk number 0 for toast value |
| Previous Message | Andrey Borodin | 2026-08-21 15:39:23 | Re: Fix XLogFileReadAnyTLI silently applying divergent WAL from wrong timeline |