NOTIFY

NOTIFY — generar una notificación

Synopsis

NOTIFY canal [ , carga_útil ]

Descripción

El comando NOTIFY envía un evento de notificación junto con una cadena opcional de carga útil (payload) a cada aplicación cliente que haya ejecutado previamente LISTEN canal para el nombre de canal especificado en la base de datos actual. Las notificaciones son visibles para todos los usuarios.

NOTIFY proporciona un mecanismo simple de comunicación entre procesos para una colección de procesos que acceden a la misma base de datos de PostgreSQL. Se puede enviar una cadena de carga útil junto con la notificación, y se pueden construir mecanismos de nivel superior para pasar datos estructurados utilizando tablas en la base de datos para pasar datos adicionales del notificador al/a los oyente(s).

La información que se pasa al cliente para un evento de notificación incluye el nombre del canal de notificación, el PID del proceso del servidor de la sesión notificadora y la cadena de carga útil, que es una cadena vacía si no se ha especificado.

Corresponde al diseñador de la base de datos definir los nombres de los canales que se utilizarán en una base de datos determinada y qué significa cada uno. Comúnmente, el nombre del canal es el mismo que el nombre de alguna tabla en la base de datos, y el evento de notificación significa esencialmente: He cambiado esta tabla, échale un vistazo para ver qué hay de nuevo. Pero los comandos NOTIFY y LISTEN no imponen tal asociación. Por ejemplo, un diseñador de bases de datos podría utilizar varios nombres de canales diferentes para indicar diferentes tipos de cambios en una sola tabla. Alternativamente, la cadena de carga útil podría usarse para diferenciar varios casos.

Cuando se utiliza NOTIFY para señalar la ocurrencia de cambios en una tabla en particular, una técnica de programación útil es colocar el NOTIFY en un disparador a nivel de sentencia (statement trigger) que se activa por las actualizaciones de la tabla. De esta manera, la notificación ocurre automáticamente cuando se cambia la tabla, y el programador de la aplicación no puede olvidarse accidentalmente de hacerlo.

NOTIFY interactúa con las transacciones SQL de algunas maneras importantes. En primer lugar, si se ejecuta un NOTIFY dentro de una transacción, los eventos de notificación no se entregan hasta y a menos que la transacción se confirme. Esto es apropiado, ya que si la transacción se aborta, todos los comandos dentro de ella no han tenido efecto, incluido NOTIFY. Pero puede ser desconcertante si uno espera que los eventos de notificación se entreguen de inmediato. En segundo lugar, si una sesión oyente recibe una señal de notificación mientras está dentro de una transacción, el evento de notificación no se entregará a su cliente conectado hasta justo después de que se complete la transacción (ya sea confirmada o abortada). De nuevo, el razonamiento es que si una notificación se entregara dentro de una transacción que luego se abortara, uno querría que la notificación se deshiciera de alguna manera; pero el servidor no puede retirar una notificación una vez que la ha enviado al cliente. Por lo tanto, los eventos de notificación solo se entregan entre transacciones. El resultado de esto es que las aplicaciones que utilizan NOTIFY para señalización en tiempo real deberían intentar mantener sus transacciones cortas.

Si se envía una señal al mismo nombre de canal varias veces con cadenas de carga útil idénticas dentro de la misma transacción, solo se entrega una instancia del evento de notificación a los oyentes. Por otro lado, las notificaciones con cadenas de carga útil distintas siempre se entregarán como notificaciones distintas. Del mismo modo, las notificaciones de diferentes transacciones nunca se fusionarán en una sola notificación. A excepción de descartar las instancias posteriores de notificaciones duplicadas, NOTIFY garantiza que las notificaciones de la misma transacción se entreguen en el orden en que fueron enviadas. También se garantiza que los mensajes de diferentes transacciones se entreguen en el orden en que se confirmaron las transacciones.

Es común que un cliente que ejecuta NOTIFY esté escuchando en el mismo canal de notificación. En ese caso, recibirá un evento de notificación, al igual que todas las demás sesiones oyentes. Dependiendo de la lógica de la aplicación, esto podría resultar en trabajo inútil, por ejemplo, leer una tabla de base de datos para encontrar las mismas actualizaciones que esa sesión acaba de escribir. Es posible evitar ese trabajo adicional observando si el PID del proceso del servidor de la sesión notificadora (suministrado en el mensaje del evento de notificación) es el mismo que el PID de la propia sesión (disponible desde libpq). Cuando son iguales, el evento de notificación es el propio trabajo que rebota y puede ignorarse.

Parámetros

canal

Nombre del canal de notificación al que enviar la señal (cualquier identificador).

carga_útil

La cadena de carga útil (payload) que se comunicará junto con la notificación. Debe especificarse como una cadena literal simple. En la configuración por omisión debe ser inferior a 8000 bytes. (Si es necesario comunicar datos binarios o grandes cantidades de información, lo mejor es colocarlos en una tabla de base de datos y enviar la clave del registro).

Notas

Existe una cola que contiene las notificaciones que se han enviado pero que aún no han sido procesadas por todas las sesiones oyentes. Si esta cola se llena, las transacciones que llaman a NOTIFY fallarán al confirmarse. La cola es bastante grande (8 GB en una instalación estándar) y debería tener un tamaño suficiente para casi cualquier caso de uso. Sin embargo, no se puede realizar ninguna limpieza si una sesión ejecuta LISTEN y luego entra en una transacción durante mucho tiempo. Una vez que la cola esté medio llena, verás advertencias en el archivo de registro que te indicarán la sesión que está impidiendo la limpieza. En este caso, debes asegurarte de que esta sesión finalice su transacción actual para que la limpieza pueda continuar.

La función pg_notification_queue_usage devuelve la fracción de la cola que está ocupada actualmente por notificaciones pendientes. Consulta la Section 9.27 para obtener más información.

Una transacción que ha ejecutado NOTIFY no se puede preparar para una confirmación en dos fases (two-phase commit).

pg_notify

Para enviar una notificación también puedes utilizar la función pg_notify(text, text). La función toma el nombre del canal como primer argumento y la carga útil como segundo. La función es mucho más fácil de usar que el comando NOTIFY si necesitas trabajar con nombres de canales y cargas útiles no constantes.

Ejemplos

Configurar y ejecutar una secuencia listen/notify desde 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.

Compatibilidad

No hay ninguna sentencia NOTIFY en el estándar SQL.

Véase también

LISTEN, UNLISTEN, max_notify_queue_pages