NOTIFY
NOTIFY — Generate a notification
Synopsis
NOTIFY channel [ , payload ]
Description
The NOTIFY command sends a notification event along with an optional "payload" string to each client application that is currently listening, having previously executed LISTEN channel for the specified channel name in the current database. Notifications are visible to all users.
NOTIFY provides a simple inter-process communication mechanism for a set of processes accessing the same Halo database. A payload string can be sent along with the notification, and higher-level mechanisms for transmitting structured data can be built by using tables in the database to pass additional data from the notifier to the listener.
The information delivered to the client by a notification event includes the notification channel name, the server process PID of the session that sent the notification, and the payload string, which is an empty string if not specified.
Channel names used within a given database and other databases are defined by the database designer. Typically, the channel name is the same as the name of a table in the database, and the notification event essentially means: "I have changed this table, come see what changed." However, the NOTIFY and LISTEN commands do not enforce such an association. For example, a database designer could use several different channel names to indicate different types of changes on a single table. Additionally, the payload string can be used in many different scenarios.
When NOTIFY is used to signal changes to a particular table, a useful programming technique is to place the NOTIFY in a statement trigger that fires on table updates. In this way, notifications are sent automatically whenever the table is changed, and application programmers cannot forget to send notifications.
NOTIFY interacts with SQL transactions in some important ways. First, if a NOTIFY is executed within a transaction, the notification event will not be delivered until the transaction is committed. This is appropriate, because if the transaction is aborted, none of its commands will have any effect, including NOTIFY. However, this behavior can be surprising if you expect notification events to be delivered immediately. Second, if a listening session receives a notification signal while it is in a transaction, the notification event will not be delivered to its connected client until the transaction completes (commit or abort). The reason is the same: if a notification is delivered within a transaction and the transaction is later aborted, we would want the notification to somehow be revoked — but the server cannot "take it back" once it has sent the notification to the client. Therefore, notification events can only be delivered between transactions. The key point is that applications using NOTIFY as a real-time signal should keep their transactions as short as possible.
If NOTIFY is called multiple times with the same payload string on the same channel name within the same transaction, only one instance of the notification event is delivered to listeners. On the other hand, notifications with different payload strings will always be delivered as distinct notifications. Similarly, notifications from different transactions will not be folded into one notification. Besides discarding later-generated duplicate notification instances, NOTIFY guarantees that notifications from the same transaction are delivered in the order they were sent. It is also guaranteed that messages from different transactions are delivered in the order their transactions were committed.
It is common for a client executing NOTIFY to also be listening on the same notification channel itself. In this case, like all other listening sessions, it will receive a notification event. Depending on application logic, this may result in unnecessary work, such as reading the same update from a table that was just written to. This extra work can be avoided by checking whether the server process PID that sent the notification (provided in the notification event message) is the same as the current session's PID (available from libpq). When they are the same, the notification event was sent by the current session itself, so it can be ignored.
Parameters
channel
The name of the notification channel to signal (any identifier).
payload
The "payload" string to communicate via the notification. This must be a simple string. In the default configuration, the string must not exceed 8000 bytes (if you need to send binary data or more information, it is best to place it in a database table and send the record's key).
Notes
A queue holds notifications that have been sent but not yet processed by all listening sessions. If the queue is full, the transaction calling NOTIFY will fail at commit time. The queue is very large (8GB in a standard installation) and should be sufficient for almost every use case. However, if a session executes NOTIFY and then enters a long-running transaction, no cleanup will occur. Once the queue is more than half full, you will see warnings in the log files indicating which session is preventing cleanup. In this case, you should ensure that the session ends its current transaction so that cleanup can proceed.
The function pg_notification_queue_usage returns the fraction of the queue currently occupied by pending notifications.
A transaction that has executed NOTIFY cannot be prepared for two-phase commit.
pg_notify
To send a notification, you can also use the function pg_notify(text, text). This function takes the channel name as its first argument and the payload as its second argument. If you need to use non-constant channel names and payloads, this function is easier to use than the NOTIFY command.
Examples
-- Configure and execute a listen/notify sequence from psql:
LISTEN virtual;
NOTIFY virtual;
Asynchronous notification "virtual" received from server process with PID 8448.
NOTIFY virtual, 'This is the payload';
Asynchronous notification "virtual" with payload "This is the payload" received
from server process with PID 8448.
LISTEN foo;
SELECT pg_notify('fo' || 'o', 'pay' || 'load');
See Also
LISTEN, UNLISTEN