pgpool: Feature: send sync message only to necessary backends.

From: Tatsuo Ishii <ishii(at)postgresql(dot)org>
To: pgpool-committers(at)lists(dot)postgresql(dot)org
Subject: pgpool: Feature: send sync message only to necessary backends.
Date: 2026-01-06 12:58:30
Message-ID: E1vd6dq-00G49u-0x@gothos.postgresql.org
Views: Whole Thread | Raw Message | Download mbox | Resend email
Thread:
Lists: pgpool-committers

Feature: send sync message only to necessary backends.

Currently pgpool forwards sync messages to all configure backend nodes
regardless the backend_weight or load_balance_mode. This is not only
a waste of CPU cycle, but degrades performance since it takes more
message round trip time as the number of backend nodes increases. This
is conspicuous if backend nodes are in a distant location. We should
send sync messages only to necessary backend nodes.

The idea is, if pgpool does not send any query message to a backend
until now (more precisely since the last ReadyForQuery message), we
don't need to send a sync message to the backend node.

To decide which node we need to send the sync message, add a new
struct member "sync_map" to the session context. A sync_map is an
array of bool. Each array member corresponds to each backend
node. When pgpool forwards a message to backend, corresponding
sync_map member is set to true.

When a sync message is received from frontend, a sync pending message
is added as we already do. The difference is, previously no query
context is added to the sync pending message. Now we add a query
context with the sync map translated into where_to_send map in the
query context. Then we send a sync message to backend, consulting the
where_to_send map. This way, we don't need to send a sync message to
backend node which pgpool has never sent a query since the last
ReadyForQuery message.

When a Ready for query message arrives, we decide which backend to
read according to the where_to_send map, which is different from what
we do today: read from all available backend nodes. After receiving
the ReadyForQuery message, sync_map members are all set to false. Also
the sync message query context is destroyed at this timing.

There are a few other edge cases:

(1) When an ErrorResponse is received,
pool_discard_except_sync_and_ready_for_query() is called to remove any
pending messages (and backend buffer data) except sync pending message
and ReadyForQuery message. If the sync message is not found in the
queue and receives a sync message from frontend, add a new sync
pending message, consulting the sync_map as described above and
forward the sync message to backends.

(2) If no query is sent and a sync message is received, the sync_map
is all false. This doesn't make sense since there's no point to send a
sync message, but the protocol does not prohibit this. In this case we
set sync_map all true, which means we send sync messages to all
backend. This may not be the best way in terms of performance, but
this makes things simpler (and compatible what we are doing today).

Author: Tatsuo Ishii <ishii(at)postgresql(dot)org>
Discussion: https://www.postgresql.org/message-id/20251225.162600.1040566325464308671.ishii%40postgresql.org

Branch
------
master

Details
-------
https://git.postgresql.org/gitweb?p=pgpool2.git;a=commitdiff;h=a350afd700478d3796aa309e082d1f93c6be18b0

Modified Files
--------------
src/context/pool_query_context.c | 22 ++--
src/context/pool_session_context.c | 40 +++++++-
src/include/context/pool_query_context.h | 5 +-
src/include/context/pool_session_context.h | 11 +-
src/protocol/pool_process_query.c | 18 +++-
src/protocol/pool_proto_modules.c | 112 +++++++++++++++++++--
src/test/regression/tests/006.memqcache/test.sh | 6 ++
.../tests/039.log_backend_messages/expected.s | 1 -
src/test/regression/tests/130.declare/test.sh | 1 +
9 files changed, 191 insertions(+), 25 deletions(-)

Browse pgpool-committers by date

  From Date Subject
Next Message Tatsuo Ishii 2026-01-07 02:18:06 pgpool: Fix new defects pointed out by Coverity.
Previous Message Tatsuo Ishii 2026-01-06 11:25:43 pgpool: Fix health check process to not start.