Быстрый старт
Развертывание
Моделирование данных
Подключение
Запись данных
Миграция
Запросы
Операции и обслуживание
Типовое обслуживание
Секционирование
Резервное копирование и восстановление
Масштабирование
Зеркалирование
Управление ресурсами
Безопасность
Мониторинг
Настройка производительности
Устранение неполадок
Справочник
Руководство по инструментам
Типы данных
Хранилище данных
Выполняющая система
Потоковая передача
Восстановление после сбоев
Конфигурация
Индексы
Расширения
Справочник по SQL
Часто задаваемые вопросы
Генерирует уведомление.
NOTIFY <channel> [ , <payload> ]
Команда NOTIFY отправляет событие уведомления вместе с необязательной строкой «полезной нагрузки» каждому клиентскому приложению, которое ранее выполнило команду LISTEN <channel> для указанного имени канала в текущей базе данных. Уведомления видны всем пользователям.
NOTIFY предоставляет простой механизм межпроцессного взаимодействия для набора процессов, обращающихся к одной и той же базе данных. Вместе с уведомлением может быть отправлена строка полезной нагрузки, а более сложные механизмы передачи структурированных данных можно реализовать, используя таблицы в базе данных для передачи дополнительных данных от отправителя уведомления к его получателям.
Информация, передаваемая клиенту при событии уведомления, включает имя канала уведомления, PID серверного процесса сессии, отправившей уведомление, и строку полезной нагрузки, которая является пустой строкой, если она не была указана.
Проектировщик базы данных должен определить, какие имена каналов будут использоваться в конкретной базе данных, и что означает каждый из них. Обычно имя канала совпадает с именем какой-либо таблицы в базе данных, и событие уведомления по сути означает: «Я изменил эту таблицу, взгляните на неё, чтобы узнать, что нового». Однако такие ассоциации не поддерживаются принудительно командами NOTIFY и LISTEN. Например, проектировщик базы данных может использовать несколько различных имён каналов для сигнализации различных типов изменений одной и той же таблицы. Альтернативно, различия между случаями могут кодироваться в строке полезной нагрузки.
Когда NOTIFY используется для сигнализации о наличии изменений в определённой таблице, полезным методом программирования является размещение команды NOTIFY в триггере оператора, который активируется при обновлении таблицы. Таким образом, уведомление происходит автоматически при изменении таблицы, и программист не может случайно забыть о нём.
NOTIFY взаимодействует с SQL-транзакциями несколькими важными способами. Во-первых, если NOTIFY выполняется внутри транзакции, события уведомления не доставляются до тех пор, пока транзакция не будет зафиксирована (committed). Это логично, поскольку если транзакция прерывается, все команды внутри неё, включая NOTIFY, считаются не выполненными. Однако это может вызвать недоумение, если ожидается немедленная доставка уведомлений. Во-вторых, если сеанс, ожидающий уведомления, получает сигнал уведомления во время выполнения транзакции, событие уведомления не будет доставлено подключённому клиенту до момента завершения транзакции (будь то фиксация или откат). Причина в том, что если бы уведомление было доставлено внутри транзакции, которая впоследствии была отменена, потребовалось бы каким-то образом «отменить» уведомление — но сервер не может «забрать обратно» уведомление, уже отправленное клиенту. Поэтому события уведомлений доставляются только между транзакциями. Из этого следует, что приложения, использующие NOTIFY для передачи информации в реальном времени, должны стремиться делать свои транзакции короткими.
Если одно и то же имя канала сигнализируется несколько раз в рамках одной транзакции с одинаковыми строками полезной нагрузки, сервер базы данных может решить отправить только одно уведомление. С другой стороны, база данных всегда доставляет уведомления с различными строками полезной нагрузки как отдельные уведомления. Аналогично, уведомления из разных транзакций никогда не объединяются в одно. За исключением отбрасывания последующих дублирующих уведомлений, NOTIFY гарантирует, что уведомления из одной транзакции доставляются в порядке их отправки. Также гарантируется, что сообщения из разных транзакций доставляются в порядке фиксации этих транзакций.
Часто клиент, выполняющий NOTIFY, сам прослушивает тот же канал уведомлений. В этом случае он также получит событие уведомления, как и все другие прослушивающие сеансы. В зависимости от логики приложения, это может привести к бесполезной работе, например, к повторному чтению таблицы базы данных для поиска тех же самых обновлений, которые были только что записаны этой сессией. Такую лишнюю работу можно избежать, проверяя, совпадает ли PID серверного процесса сессии, отправившей уведомление (передаваемый в сообщении события уведомления), с PID собственной сессии (доступен через libpq). Если они совпадают, значит, полученное уведомление — это собственное действие, отразившееся назад, и его можно игнорировать.
Существует очередь, в которой хранятся уведомления, отправленные, но ещё не обработанные всеми прослушивающими сессиями. Если эта очередь заполнится полностью, транзакции, вызывающие NOTIFY, будут завершаться ошибкой при фиксации. Очередь достаточно велика (8 ГБ при стандартной установке) и должна быть достаточной для почти всех случаев использования. Однако очистка очереди невозможна, если сеанс выполнил LISTEN и затем надолго остался внутри транзакции. Когда очередь заполнится наполовину, в файле журнала появятся предупреждения, указывающие на сеанс, мешающий очистке. В таком случае необходимо убедиться, что этот сеанс завершает свою текущую транзакцию, чтобы очистка могла продолжиться.
Функция pg_notification_queue_usage() возвращает долю очереди, занятую ожидающими уведомлениями.
Транзакция, выполнившая NOTIFY, не может быть подготовлена для двухфазной фиксации (two-phase commit).
Для отправки уведомления вы можете также использовать функцию 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.