| From: | Hannu Krosing <hannuk(at)google(dot)com> |
|---|---|
| To: | pgsql-hackers <pgsql-hackers(at)postgresql(dot)org> |
| Subject: | [PATCH] Extensible ReadyForQuery wire protocol message and C hook, for connection pools and WAIT FOR LSN |
| Date: | 2026-10-08 09:35:27 |
| Message-ID: | CAMT0RQSP2Qopgr+5Z5NH1wur17=2fs0VAn5v3F8TtyQEApCmAQ@mail.gmail.com |
| Views: | Whole Thread | Raw Message | Download mbox | Resend email |
| Thread: | |
| Lists: | pgsql-hackers |
Hi hackers,
One of the persistent challenges for connection poolers (PgBouncer, pgpool-II,
Odyssey) and connection routers in transaction-pooling mode is determining
whether a backend connection is clean enough to be safely recycled back into
the pool without issuing expensive round-trip cleanup probes (such as
DISCARD ALL,
querying pg_prepared_xacts, or checking for active WITH HOLD cursors
or temporary
namespaces).
Similarly, with the introduction of replication wait commands (such as
WAIT FOR LSN / pg_wal_replay_wait()), proxies and clients wishing to achieve
causal consistency (read-your-own-writes across read replicas) need to know
the commit LSN of the transaction just completed on the primary backend without
incurring the round-trip overhead of an extra SELECT
pg_current_wal_insert_lsn().
To address this, the attached patch introduces an extensible ReadyForQuery ('Z')
frontend/backend wire protocol message format and a corresponding C hook
(ready_for_query_hook).
Key highlights:
1. GUC Parameter: ready_for_query_message
- Enum with values 'plain' (default) and 'rich'.
- Context PGC_USERSET with GUC_REPORT.
- When 'plain', the protocol message is completely unchanged (5-byte length).
- When 'rich', the message length header is expanded to include additional
length-prefixed key-value pairs:
[uint8 key_len][key_bytes][uint8 val_len][val_bytes].
QUESTION: do we want a more detailed setting, like
SET ready_for_query_message = "rich:THL"
to sent only these three?
2. Built-in Session State Indicators (in 'rich' mode):
- 'T': "1" if temporary tables/schemas are active, "0" otherwise
(O(1) check).
- 'H': "1" if active WITH HOLD cursors exist in the session, "0" otherwise.
- 'P': "1" if active 2PC prepared transactions exist, "0" otherwise.
- 'L': Last transaction commit LSN as text (from XactLastCommitEnd).
3. C Hook: ready_for_query_hook
- Declared as: typedef void (*ready_for_query_hook_type) (StringInfo buf);
- Extensions can register this hook and use ready_for_query_has_key()
and ready_for_query_append_kv() to add custom contextual metadata
(e.g., custom session flags, tenant tags, or replication state).
4. Protocol Compatibility:
- Unless you set ready_for_query_message=rich the protocol does not
change at all
- libpq (fe-protocol3.c) is updated so that clients ignore any trailing
extension bytes in ReadyForQuery messages if they receive them, ensuring
full forward and backward compatibility.
5. Tests & Documentation:
- Documentation added in doc/src/sgml/protocol.sgml and
doc/src/sgml/config.sgml.
- Test module src/test/modules/test_ready_for_query includes both
SQL regression
and TAP test suites validating standard/rich modes, startup options,
temp tables, cursors, 2PC, LSN, and hook injection.
The patch applies cleanly against current master. Feedback and suggestions are
welcome.
Regards,
Hannu Krosing
| Attachment | Content-Type | Size |
|---|---|---|
| 0001-Extend-ReadyForQuery-wire-protocol-message-and-provi.patch | application/x-patch | 31.2 KB |
| From | Date | Subject | |
|---|---|---|---|
| Next Message | Osama Abdul Qader | 2026-10-08 09:37:32 | Re: Regress test might fail due to deadlock between domain and alter_table |
| Previous Message | Manu | 2026-10-08 09:34:50 | Re: Add a hint to the "WAL summaries are required" errors |