NOTIFY#

NOTIFY

NOTIFY

NOTIFY — создать уведомление

Синтаксис

NOTIFY channel [ , payload ]

Описание

Команда NOTIFY отправляет уведомление вместе с необязательной строкой payload каждому клиентскому приложению, которое ранее выполнило команду LISTEN channel для указанного имени канала в текущей базе данных. Уведомления видны всем пользователям.

NOTIFY предоставляет простой механизм межпроцессного взаимодействия для набора процессов, обращающихся к одной и той же базе данных Tantor SE. Вместе с уведомлением может быть отправлена строка данных, и высокоуровневые механизмы для передачи структурированных данных могут быть построены с использованием таблиц в базе данных для передачи дополнительных данных от отправителя к слушателям.

Информация, передаваемая клиенту для события уведомления, включает имя канала уведомления, идентификатор процесса сервера, отвечающего за уведомление (PID), и строку данных (payload), которая является пустой, если она не была указана.

Это зависит от разработчика базы данных определить имена каналов, которые будут использоваться в данной базе данных, и что означает каждый из них. Обычно имя канала совпадает с именем некоторой таблицы в базе данных, и событие уведомления фактически означает: Я изменил эту таблицу, посмотрите на нее, чтобы увидеть, что нового. Однако никакое такое соответствие не обязательно для команд NOTIFY и LISTEN. Например, разработчик базы данных может использовать несколько разных имен каналов для сигнализации различных видов изменений в одной таблице. В качестве альтернативы, строка данных может использоваться для различения различных случаев.

Когда NOTIFY используется для сигнализации о возникновении изменений в определенной таблице, полезной программной техникой является помещение NOTIFY в триггер оператора, который срабатывает при обновлении таблицы. Таким образом, уведомление происходит автоматически при изменении таблицы, и программист приложения не может случайно забыть это сделать.

NOTIFY взаимодействует с SQL-транзакциями в некоторых важных аспектах. Во-первых, если NOTIFY выполняется внутри транзакции, события уведомления не будут доставлены до тех пор, пока транзакция не будет подтверждена. Это соответствует логике, поскольку если транзакция отменяется, все команды внутри нее не имеют эффекта, включая NOTIFY. Но это может вызвать недоумение, если ожидается, что события уведомления будут доставлены немедленно. Во-вторых, если прослушивающая сессия получает сигнал уведомления во время выполнения транзакции, событие уведомления не будет доставлено подключенному клиенту до тех пор, пока транзакция не будет завершена (подтверждена или отменена). Опять же, рассуждение состоит в том, что если уведомление было доставлено внутри транзакции, которая позже была отменена, хотелось бы, чтобы уведомление как-то было отменено — но сервер не может отозвать уведомление после его отправки клиенту. Поэтому события уведомления доставляются только между транзакциями. В результате приложения, использующие NOTIFY для реального времени сигнализации, должны стараться делать свои транзакции короткими.

Если одно и то же имя канала сигнализируется несколько раз с идентичными строками данных в пределах одной транзакции, только одно уведомление будет доставлено слушателям. С другой стороны, уведомления с различными строками данных всегда будут доставляться как отдельные уведомления. Аналогично, уведомления из разных транзакций никогда не будут объединены в одно уведомление. За исключением удаления последующих экземпляров дублирующихся уведомлений, NOTIFY гарантирует, что уведомления из одной и той же транзакции будут доставлены в том порядке, в котором они были отправлены. Также гарантируется, что сообщения из разных транзакций будут доставлены в порядке, в котором транзакции были подтверждены.

Сообщение NOTIFY часто отправляется клиентом, который сам же и слушает канал уведомлений. В этом случае клиент получит уведомление, так же как и все остальные сессии прослушивания. В зависимости от логики приложения это может привести к бесполезной работе, например, чтению таблицы базы данных для поиска тех же самых обновлений, которые только что были записаны этой сессией. Возможно избежать такой дополнительной работы, заметив, что идентификатор процесса сервера (PID), указанный в сообщении уведомления, совпадает с PID собственной сессии (доступного из libpq). Когда они совпадают, уведомление является собственной работой, которая возвращается обратно, и его можно игнорировать.

Параметры

channel

Имя канала уведомлений, которое будет сигнализироваться (любой идентификатор).

payload

Строка payload, которую необходимо передать вместе с уведомлением. Она должна быть указана как простая строковая литера. В конфигурации по умолчанию она должна быть короче 8000 байт. (Если требуется передача двоичных данных или больших объемов информации, лучше поместить их в таблицу базы данных и отправить ключ записи).

Примечания

Существует очередь, которая содержит уведомления, отправленные, но еще не обработанные всеми прослушивающими сессиями. Если эта очередь заполняется, транзакции, вызывающие NOTIFY, завершаются с ошибкой при коммите. Очередь достаточно большая (8 ГБ в стандартной установке) и должна быть достаточно большой для практически любого случая использования. Однако, если сессия выполняет команду LISTEN и затем входит в транзакцию на очень долгое время, очистка не может произойти. Когда очередь заполняется наполовину, в журнальном файле появляются предупреждения, указывающие на сессию, который мешает очистке. В этом случае убедитесь, что этот сессия завершает текущую транзакцию, чтобы очистка могла продолжиться.

Функция pg_notification_queue_usage возвращает долю очереди, которая в настоящее время занята ожидающими уведомлениями. См. Раздел 9.26 для получения дополнительной информации.

Транзакция, которая выполнила NOTIFY, не может быть подготовлена для двухфазного коммита.

pg_notify

Для отправки уведомления вы также можете использовать функцию pg_notify(text, text). Функция принимает имя канала в качестве первого аргумента и данные в качестве второго. Функция гораздо удобнее использовать, чем команда NOTIFY, если вам нужно работать с переменными именами каналов и данными.

Примеры

Настройка и выполнение последовательности listen/notify из 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');
Asynchronous notification "foo" with payload "payload" received from server process with PID 14728.

Совместимость

В стандарте SQL нет оператора NOTIFY.

См. также

LISTEN, UNLISTEN