Re: Pgbench: remove synchronous prepare - Mailing list pgsql-hackers

From Dmitrii Bondar
Subject Re: Pgbench: remove synchronous prepare
Date
Msg-id 6e161344-d26a-4e3d-aa12-83a05a3ca8dc@postgrespro.ru
Whole thread
In response to Re: Pgbench: remove synchronous prepare  (Robert Haas <robertmhaas@gmail.com>)
Responses Re: Pgbench: remove synchronous prepare
List pgsql-hackers


On 4/27/26 12:01 AM, Robert Haas wrote:
On Mon, Mar 16, 2026 at 3:46 AM Dmitrii Bondar <d.bondar@postgrespro.ru> wrote:
Rebase.
Hi,

I think that this patch is changing more behavior than is explained in
the commit message. The existing code calls PQsendQueryPrepared, which
only tries to execute an already-prepared query. The replacement code
tries to prepare the query. It is not clear to me what's going on
here. I would have expected that we would only ever reach that point
in the code with the query already prepared; otherwise, the existing
code would presumably fail. But if that is the case then how is the
new code managing to do anything different than the old code?

Another way to see that the patch must be changing more behavior than
advertised is the change to 001_pgbench_with_server.pl. That change
comes with no comment changes and no explanation of any kind.

If this patch were just about doing something asynchronously instead
of synchronously, I think that would be fine, but I don't think that's
all that is happening here. The original post explains the problem
behavior (pgbench freezing under certain circumstances) but I don't
understand what causes that behavior. I think I would understand
better if the original complaint were about something other than
session pooling mode: then, I might expect that we might unexpectedly
discover that our session does not have something prepared which we
expected to find prepared, and maybe this revised logic in
sendCommand() would somehow fix that. But in session pooling mode,
shouldn't everything be the same as if connection pooling is not in
use at all? What's actually different?

Hi,

The patch does not change the existing behavior when a query has already been prepared. Both the old and new code paths use PQsendQueryPrepared, which sends a bind-execute-sync packet sequence without waiting for a response.

The main difference appears when the query has not yet been prepared. In the old code, PQprepare is called, which sends a parse message and then waits for the result via PQexecFinish. Since PQexecFinish blocks until a response arrives, it can block the entire thread if the server has not responded yet.

I replaced the call to PQprepare with a call to the new PQsendPBES function. Like PQsendQueryPrepared, it works asynchronously, but it sends a parse-bind-execute-sync sequence instead. This change avoids thread blocking because it eliminates the need to call PQexecFinish.

I chose to send a parse-bind-execute-sync sequence to match the behavior of extended query mode, in which pgbench sends the same sequence, but with an unnamed statement.

The expected output for 001_pgbench_with_server.pl was changed for the following reason. In the old pgbench code, prepareCommand is called and receives ERROR: syntax error. Since prepareCommand does not return a status, pgbench continues execution and then attempts to run the command with PQsendQueryPrepared. This leads to the error prepared statement .* does not exist, which is caused by the bind packet.

In the new code, PQsendPBES sends a parse-bind-execute-sync packet sequence. If the parse step fails with ERROR: syntax error, all subsequent messages are ignored until the sync packet is processed. That is why the additional prepared statement .* does not exist error from the bind packet no longer appears.

Session mode is indeed the most transparent way to use a pooler. However, pgbench can become stuck when the number of clients exceeds the pool size. If the pooler cannot reserve a backend for a client, it places the client in a waiting queue. In that case, pgbench may wait indefinitely because it is blocked in PQprepare, and the pgbench thread cannot process responses for other clients.

Regards,
Dmitrii Bondar

pgsql-hackers by date:

Previous
From: Yugo Nagata
Date:
Subject: Re: Infinite Autovacuum loop caused by failing virtual generated column expression
Next
From: Richard Guo
Date:
Subject: Re: Remove inner joins based on foreign keys