aboutsummaryrefslogtreecommitdiff
path: root/src/backend/tcop/postgres.c
diff options
context:
space:
mode:
authorTom Lane <tgl@sss.pgh.pa.us>2021-09-14 17:18:25 -0400
committerTom Lane <tgl@sss.pgh.pa.us>2021-09-14 17:18:25 -0400
commit2e4eae87d02fef51c42c2028b65d85b9e051f9eb (patch)
tree784c2af575086b29e849360926c789f8ee649994 /src/backend/tcop/postgres.c
parente8638d78a2cb94efba11a5dfbf3e7cd746d0af3e (diff)
downloadpostgresql-2e4eae87d02fef51c42c2028b65d85b9e051f9eb.tar.gz
postgresql-2e4eae87d02fef51c42c2028b65d85b9e051f9eb.zip
Send NOTIFY signals during CommitTransaction.
Formerly, we sent signals for outgoing NOTIFY messages within ProcessCompletedNotifies, which was also responsible for sending relevant ones of those messages to our connected client. It therefore had to run during the main-loop processing that occurs just before going idle. This arrangement had two big disadvantages: * Now that procedures allow intra-command COMMITs, it would be useful to send NOTIFYs to other sessions immediately at COMMIT (though, for reasons of wire-protocol stability, we still shouldn't forward them to our client until end of command). * Background processes such as replication workers would not send NOTIFYs at all, since they never execute the client communication loop. We've had requests to allow triggers running in replication workers to send NOTIFYs, so that's a problem. To fix these things, move transmission of outgoing NOTIFY signals into AtCommit_Notify, where it will happen during CommitTransaction. Also move the possible call of asyncQueueAdvanceTail there, to ensure we don't bloat the async SLRU if a background worker sends many NOTIFYs with no one listening. We can also drop the call of asyncQueueReadAllNotifications, allowing ProcessCompletedNotifies to go away entirely. That's because commit 790026972 added a call of ProcessNotifyInterrupt adjacent to PostgresMain's call of ProcessCompletedNotifies, and that does its own call of asyncQueueReadAllNotifications, meaning that we were uselessly doing two such calls (inside two separate transactions) whenever inbound notify signals coincided with an outbound notify. We need only set notifyInterruptPending to ensure that ProcessNotifyInterrupt runs, and we're done. The existing documentation suggests that custom background workers should call ProcessCompletedNotifies if they want to send NOTIFY messages. To avoid an ABI break in the back branches, reduce it to an empty routine rather than removing it entirely. Removal will occur in v15. Although the problems mentioned above have existed for awhile, I don't feel comfortable back-patching this any further than v13. There was quite a bit of churn in adjacent code between 12 and 13. At minimum we'd have to also backpatch 51004c717, and a good deal of other adjustment would also be needed, so the benefit-to-risk ratio doesn't look attractive. Per bug #15293 from Michael Powers (and similar gripes from others). Artur Zakirov and Tom Lane Discussion: https://postgr.es/m/153243441449.1404.2274116228506175596@wrigleys.postgresql.org
Diffstat (limited to 'src/backend/tcop/postgres.c')
-rw-r--r--src/backend/tcop/postgres.c16
1 files changed, 7 insertions, 9 deletions
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 58b5960e27d..3f9ed549f92 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -504,7 +504,7 @@ ProcessClientReadInterrupt(bool blocked)
/* Process notify interrupts, if any */
if (notifyInterruptPending)
- ProcessNotifyInterrupt();
+ ProcessNotifyInterrupt(true);
}
else if (ProcDiePending)
{
@@ -4373,17 +4373,15 @@ PostgresMain(int argc, char *argv[],
}
else
{
- /* Send out notify signals and transmit self-notifies */
- ProcessCompletedNotifies();
-
/*
- * Also process incoming notifies, if any. This is mostly to
- * ensure stable behavior in tests: if any notifies were
- * received during the just-finished transaction, they'll be
- * seen by the client before ReadyForQuery is.
+ * Process incoming notifies (including self-notifies), if
+ * any, and send relevant messages to the client. Doing it
+ * here helps ensure stable behavior in tests: if any notifies
+ * were received during the just-finished transaction, they'll
+ * be seen by the client before ReadyForQuery is.
*/
if (notifyInterruptPending)
- ProcessNotifyInterrupt();
+ ProcessNotifyInterrupt(false);
pgstat_report_stat(false);