diff --git a/doc/src/sgml/ref/notify.sgml b/doc/src/sgml/ref/notify.sgml index fd6ed54e8f9d8..484868d556b63 100644 --- a/doc/src/sgml/ref/notify.sgml +++ b/doc/src/sgml/ref/notify.sgml @@ -175,6 +175,73 @@ NOTIFY channel [ , + + Performance Considerations + + + So that notifications are queued in commit order, a transaction that has + executed NOTIFY takes a heavyweight lock during commit + that serializes it against every other committing transaction that has + executed NOTIFY. This lock is cluster-wide, not + per-database: notifying transactions running in different databases of the + same cluster contend with one another. Transactions that have not executed + NOTIFY do not take this lock, and + LISTEN and UNLISTEN do not take it + either. + + + + The lock is held until the notifying transaction's commit is complete, + which includes flushing the transaction's WAL records to + disk and, if synchronous replication is in use, waiting for the standby + server(s) to respond. Notifying transactions therefore cannot be + group-committed with one another: each one pays for a commit round trip on + its own, and the aggregate rate of notifying transactions is limited to + roughly one such round trip at a time, no matter how many client sessions + are active. The effect is correspondingly larger when commits are + expensive, that is with set to + on, with + configured, or on storage with high write latency. + + + + The cost is incurred once per notifying transaction, not once per + notification, since a transaction that sends many notifications takes the + lock only once. Applications that need a high notification rate should + therefore accumulate notifications and send them from as few transactions + as possible. In particular, avoid executing NOTIFY in a + row-level trigger; collect the notifications in a statement-level trigger + instead, or send a single notification per transaction and let listeners + determine what changed. + + + + To diagnose this contention, look for sessions with + wait_event_type Lock and + wait_event object in + pg_stat_activity. + Reporting in the server log via is also + possible, but note that it only reports waits exceeding + , whose default of one second is + typically far longer than an individual wait for this lock, so that setting + must usually be reduced before any such wait is logged. The wait is + reported as AccessExclusiveLock on object 0 of class 1262 of + database 0. A characteristic symptom of this contention is that + transaction throughput falls while CPU and disk + utilization fall as well, because the waiting sessions are idle rather than + busy. + + + + If the required notification rate cannot be reduced by batching, consider + another mechanism: a queue table that consumers poll using + SELECT ... FOR UPDATE SKIP LOCKED (see + ) does not serialize commits, and + is a better fit when the goal is to + stream data changes to an external consumer. + + + pg_notify