]> begriffs open source - ai-pg/blob - full-docs/txt/libpq-pipeline-mode.txt
Convert HTML docs to more streamlined TXT
[ai-pg] / full-docs / txt / libpq-pipeline-mode.txt
1
2 32.5. Pipeline Mode #
3
4    32.5.1. Using Pipeline Mode
5    32.5.2. Functions Associated with Pipeline Mode
6    32.5.3. When to Use Pipeline Mode
7
8    libpq pipeline mode allows applications to send a query without having
9    to read the result of the previously sent query. Taking advantage of
10    the pipeline mode, a client will wait less for the server, since
11    multiple queries/results can be sent/received in a single network
12    transaction.
13
14    While pipeline mode provides a significant performance boost, writing
15    clients using the pipeline mode is more complex because it involves
16    managing a queue of pending queries and finding which result
17    corresponds to which query in the queue.
18
19    Pipeline mode also generally consumes more memory on both the client
20    and server, though careful and aggressive management of the
21    send/receive queue can mitigate this. This applies whether or not the
22    connection is in blocking or non-blocking mode.
23
24    While libpq's pipeline API was introduced in PostgreSQL 14, it is a
25    client-side feature which doesn't require special server support and
26    works on any server that supports the v3 extended query protocol. For
27    more information see Section 54.2.4.
28
29 32.5.1. Using Pipeline Mode #
30
31    To issue pipelines, the application must switch the connection into
32    pipeline mode, which is done with PQenterPipelineMode. PQpipelineStatus
33    can be used to test whether pipeline mode is active. In pipeline mode,
34    only asynchronous operations that utilize the extended query protocol
35    are permitted, command strings containing multiple SQL commands are
36    disallowed, and so is COPY. Using synchronous command execution
37    functions such as PQfn, PQexec, PQexecParams, PQprepare,
38    PQexecPrepared, PQdescribePrepared, PQdescribePortal, PQclosePrepared,
39    PQclosePortal, is an error condition. PQsendQuery is also disallowed,
40    because it uses the simple query protocol. Once all dispatched commands
41    have had their results processed, and the end pipeline result has been
42    consumed, the application may return to non-pipelined mode with
43    PQexitPipelineMode.
44
45 Note
46
47    It is best to use pipeline mode with libpq in non-blocking mode. If
48    used in blocking mode it is possible for a client/server deadlock to
49    occur. ^[15]
50
51 32.5.1.1. Issuing Queries #
52
53    After entering pipeline mode, the application dispatches requests using
54    PQsendQueryParams or its prepared-query sibling PQsendQueryPrepared.
55    These requests are queued on the client-side until flushed to the
56    server; this occurs when PQpipelineSync is used to establish a
57    synchronization point in the pipeline, or when PQflush is called. The
58    functions PQsendPrepare, PQsendDescribePrepared, PQsendDescribePortal,
59    PQsendClosePrepared, and PQsendClosePortal also work in pipeline mode.
60    Result processing is described below.
61
62    The server executes statements, and returns results, in the order the
63    client sends them. The server will begin executing the commands in the
64    pipeline immediately, not waiting for the end of the pipeline. Note
65    that results are buffered on the server side; the server flushes that
66    buffer when a synchronization point is established with either
67    PQpipelineSync or PQsendPipelineSync, or when PQsendFlushRequest is
68    called. If any statement encounters an error, the server aborts the
69    current transaction and does not execute any subsequent command in the
70    queue until the next synchronization point; a PGRES_PIPELINE_ABORTED
71    result is produced for each such command. (This remains true even if
72    the commands in the pipeline would rollback the transaction.) Query
73    processing resumes after the synchronization point.
74
75    It's fine for one operation to depend on the results of a prior one;
76    for example, one query may define a table that the next query in the
77    same pipeline uses. Similarly, an application may create a named
78    prepared statement and execute it with later statements in the same
79    pipeline.
80
81 32.5.1.2. Processing Results #
82
83    To process the result of one query in a pipeline, the application calls
84    PQgetResult repeatedly and handles each result until PQgetResult
85    returns null. The result from the next query in the pipeline may then
86    be retrieved using PQgetResult again and the cycle repeated. The
87    application handles individual statement results as normal. When the
88    results of all the queries in the pipeline have been returned,
89    PQgetResult returns a result containing the status value
90    PGRES_PIPELINE_SYNC
91
92    The client may choose to defer result processing until the complete
93    pipeline has been sent, or interleave that with sending further queries
94    in the pipeline; see Section 32.5.1.4.
95
96    PQgetResult behaves the same as for normal asynchronous processing
97    except that it may contain the new PGresult types PGRES_PIPELINE_SYNC
98    and PGRES_PIPELINE_ABORTED. PGRES_PIPELINE_SYNC is reported exactly
99    once for each PQpipelineSync or PQsendPipelineSync at the corresponding
100    point in the pipeline. PGRES_PIPELINE_ABORTED is emitted in place of a
101    normal query result for the first error and all subsequent results
102    until the next PGRES_PIPELINE_SYNC; see Section 32.5.1.3.
103
104    PQisBusy, PQconsumeInput, etc operate as normal when processing
105    pipeline results. In particular, a call to PQisBusy in the middle of a
106    pipeline returns 0 if the results for all the queries issued so far
107    have been consumed.
108
109    libpq does not provide any information to the application about the
110    query currently being processed (except that PQgetResult returns null
111    to indicate that we start returning the results of next query). The
112    application must keep track of the order in which it sent queries, to
113    associate them with their corresponding results. Applications will
114    typically use a state machine or a FIFO queue for this.
115
116 32.5.1.3. Error Handling #
117
118    From the client's perspective, after PQresultStatus returns
119    PGRES_FATAL_ERROR, the pipeline is flagged as aborted. PQresultStatus
120    will report a PGRES_PIPELINE_ABORTED result for each remaining queued
121    operation in an aborted pipeline. The result for PQpipelineSync or
122    PQsendPipelineSync is reported as PGRES_PIPELINE_SYNC to signal the end
123    of the aborted pipeline and resumption of normal result processing.
124
125    The client must process results with PQgetResult during error recovery.
126
127    If the pipeline used an implicit transaction, then operations that have
128    already executed are rolled back and operations that were queued to
129    follow the failed operation are skipped entirely. The same behavior
130    holds if the pipeline starts and commits a single explicit transaction
131    (i.e. the first statement is BEGIN and the last is COMMIT) except that
132    the session remains in an aborted transaction state at the end of the
133    pipeline. If a pipeline contains multiple explicit transactions, all
134    transactions that committed prior to the error remain committed, the
135    currently in-progress transaction is aborted, and all subsequent
136    operations are skipped completely, including subsequent transactions.
137    If a pipeline synchronization point occurs with an explicit transaction
138    block in aborted state, the next pipeline will become aborted
139    immediately unless the next command puts the transaction in normal mode
140    with ROLLBACK.
141
142 Note
143
144    The client must not assume that work is committed when it sends a
145    COMMIT — only when the corresponding result is received to confirm the
146    commit is complete. Because errors arrive asynchronously, the
147    application needs to be able to restart from the last received
148    committed change and resend work done after that point if something
149    goes wrong.
150
151 32.5.1.4. Interleaving Result Processing and Query Dispatch #
152
153    To avoid deadlocks on large pipelines the client should be structured
154    around a non-blocking event loop using operating system facilities such
155    as select, poll, WaitForMultipleObjectEx, etc.
156
157    The client application should generally maintain a queue of work
158    remaining to be dispatched and a queue of work that has been dispatched
159    but not yet had its results processed. When the socket is writable it
160    should dispatch more work. When the socket is readable it should read
161    results and process them, matching them up to the next entry in its
162    corresponding results queue. Based on available memory, results from
163    the socket should be read frequently: there's no need to wait until the
164    pipeline end to read the results. Pipelines should be scoped to logical
165    units of work, usually (but not necessarily) one transaction per
166    pipeline. There's no need to exit pipeline mode and re-enter it between
167    pipelines, or to wait for one pipeline to finish before sending the
168    next.
169
170    An example using select() and a simple state machine to track sent and
171    received work is in src/test/modules/libpq_pipeline/libpq_pipeline.c in
172    the PostgreSQL source distribution.
173
174 32.5.2. Functions Associated with Pipeline Mode #
175
176    PQpipelineStatus #
177           Returns the current pipeline mode status of the libpq
178           connection.
179
180 PGpipelineStatus PQpipelineStatus(const PGconn *conn);
181
182           PQpipelineStatus can return one of the following values:
183
184         PQ_PIPELINE_ON
185                 The libpq connection is in pipeline mode.
186
187         PQ_PIPELINE_OFF
188                 The libpq connection is not in pipeline mode.
189
190         PQ_PIPELINE_ABORTED
191                 The libpq connection is in pipeline mode and an error
192                 occurred while processing the current pipeline. The
193                 aborted flag is cleared when PQgetResult returns a result
194                 of type PGRES_PIPELINE_SYNC.
195
196    PQenterPipelineMode #
197           Causes a connection to enter pipeline mode if it is currently
198           idle or already in pipeline mode.
199
200 int PQenterPipelineMode(PGconn *conn);
201
202           Returns 1 for success. Returns 0 and has no effect if the
203           connection is not currently idle, i.e., it has a result ready,
204           or it is waiting for more input from the server, etc. This
205           function does not actually send anything to the server, it just
206           changes the libpq connection state.
207
208    PQexitPipelineMode #
209           Causes a connection to exit pipeline mode if it is currently in
210           pipeline mode with an empty queue and no pending results.
211
212 int PQexitPipelineMode(PGconn *conn);
213
214           Returns 1 for success. Returns 1 and takes no action if not in
215           pipeline mode. If the current statement isn't finished
216           processing, or PQgetResult has not been called to collect
217           results from all previously sent query, returns 0 (in which
218           case, use PQerrorMessage to get more information about the
219           failure).
220
221    PQpipelineSync #
222           Marks a synchronization point in a pipeline by sending a sync
223           message and flushing the send buffer. This serves as the
224           delimiter of an implicit transaction and an error recovery
225           point; see Section 32.5.1.3.
226
227 int PQpipelineSync(PGconn *conn);
228
229           Returns 1 for success. Returns 0 if the connection is not in
230           pipeline mode or sending a sync message failed.
231
232    PQsendPipelineSync #
233           Marks a synchronization point in a pipeline by sending a sync
234           message without flushing the send buffer. This serves as the
235           delimiter of an implicit transaction and an error recovery
236           point; see Section 32.5.1.3.
237
238 int PQsendPipelineSync(PGconn *conn);
239
240           Returns 1 for success. Returns 0 if the connection is not in
241           pipeline mode or sending a sync message failed. Note that the
242           message is not itself flushed to the server automatically; use
243           PQflush if necessary.
244
245    PQsendFlushRequest #
246           Sends a request for the server to flush its output buffer.
247
248 int PQsendFlushRequest(PGconn *conn);
249
250           Returns 1 for success. Returns 0 on any failure.
251
252           The server flushes its output buffer automatically as a result
253           of PQpipelineSync being called, or on any request when not in
254           pipeline mode; this function is useful to cause the server to
255           flush its output buffer in pipeline mode without establishing a
256           synchronization point. Note that the request is not itself
257           flushed to the server automatically; use PQflush if necessary.
258
259 32.5.3. When to Use Pipeline Mode #
260
261    Much like asynchronous query mode, there is no meaningful performance
262    overhead when using pipeline mode. It increases client application
263    complexity, and extra caution is required to prevent client/server
264    deadlocks, but pipeline mode can offer considerable performance
265    improvements, in exchange for increased memory usage from leaving state
266    around longer.
267
268    Pipeline mode is most useful when the server is distant, i.e., network
269    latency (“ping time”) is high, and also when many small operations are
270    being performed in rapid succession. There is usually less benefit in
271    using pipelined commands when each query takes many multiples of the
272    client/server round-trip time to execute. A 100-statement operation run
273    on a server 300 ms round-trip-time away would take 30 seconds in
274    network latency alone without pipelining; with pipelining it may spend
275    as little as 0.3 s waiting for results from the server.
276
277    Use pipelined commands when your application does lots of small INSERT,
278    UPDATE and DELETE operations that can't easily be transformed into
279    operations on sets, or into a COPY operation.
280
281    Pipeline mode is not useful when information from one operation is
282    required by the client to produce the next operation. In such cases,
283    the client would have to introduce a synchronization point and wait for
284    a full client/server round-trip to get the results it needs. However,
285    it's often possible to adjust the client design to exchange the
286    required information server-side. Read-modify-write cycles are
287    especially good candidates; for example:
288 BEGIN;
289 SELECT x FROM mytable WHERE id = 42 FOR UPDATE;
290 -- result: x=2
291 -- client adds 1 to x:
292 UPDATE mytable SET x = 3 WHERE id = 42;
293 COMMIT;
294
295    could be much more efficiently done with:
296 UPDATE mytable SET x = x + 1 WHERE id = 42;
297
298    Pipelining is less useful, and more complex, when a single pipeline
299    contains multiple transactions (see Section 32.5.1.3).
300
301    ^[15] The client will block trying to send queries to the server, but
302    the server will block trying to send results to the client from queries
303    it has already processed. This only occurs when the client sends enough
304    queries to fill both its output buffer and the server's receive buffer
305    before it switches to processing input from the server, but it's hard
306    to predict exactly when that will happen.