すべてのプロダクト
Search
ドキュメントセンター

PolarDB:注意

最終更新日:May 31, 2024

この記事では、NOTIFYの構文、パラメーター、および例を紹介します。

説明

NOTIFYコマンドは、現在のデータベース内の指定されたチャネル名に対して以前にLISTENを実行した各クライアントアプリケーションに、オプションの「ペイロード」文字列とともに通知イベントを送信します。 通知はすべてのユーザーに表示されます。

NOTIFYは、同じPolarDBデータベースにアクセスするプロセスのコレクションに対して、簡単なプロセス間通信メカニズムを提供します。 通知と共にペイロード文字列を送信することができ、データベース内のテーブルを使用して追加のデータを通知者からリスナーに渡すことにより、構造化データを渡すためのより高レベルのメカニズムを構築することができます。

通知イベントのためにクライアントに渡される情報には、通知チャネル名、通知セッションのサーバーprocessPID、および指定されていない場合は空の文字列であるペイロード文字列が含まれます。

特定のデータベースで使用されるチャネル名とそれぞれの意味を定義するのは、データベース設計者次第です。 通常、チャネル名はデータベース内のあるテーブルの名前と同じであり、通知イベントは本質的に「このテーブルを変更しました。新しいものを見るためにそれを見てください」という意味です。 しかし、そのような関連付けは、NOTIFYおよびLISTENコマンドによって実施されない。 例えば、データベース設計者は、いくつかの異なるチャネル名を使用して、単一のテーブルに対する異なる種類の変更をシグナリングすることができる。 あるいは、ペイロードストリングは、様々なケースを区別するために使用され得る。

NOTIFYを使用して特定のテーブルへの変更の発生を通知する場合、有用なプログラミング手法は、テーブルの更新によってトリガーされるステートメントトリガーにNOTIFYを入れることです。 このようにして、テーブルが変更されたときに通知が自動的に行われ、アプリケーションプログラマは誤ってそれを忘れることができません。

NOTIFYは、いくつかの重要な方法でSQLトランザクションと対話します。 第1に、NOTIFYがトランザクション内で実行される場合、通知イベントは、トランザクションがコミットされるまで配信されない。 トランザクションがアボートされた場合、NOTIFYを含む、その中のすべてのコマンドは何の影響も及ぼさないので、これは適切である。 しかし、通知イベントがすぐに配信されることを期待している場合、それは当惑する可能性があります。 第2に、リスニングセッションがトランザクション内にある間に通知信号を受信した場合、通知イベントは、トランザクションが完了 (コミットまたはアボートのいずれか) した直後まで、その接続されたクライアントに配信されない。 ここでも、後に中止されたトランザクション内で通知が配信された場合、何らかの形で通知を元に戻すことが望ましいが、サーバは、一旦クライアントに通知を送信すると、通知を「取り戻す」ことができない。 したがって、通知イベントはトランザクション間でのみ配信されます。 この結果、リアルタイムシグナリングにNOTIFYを使用するアプリケーションは、トランザクションを短くしようとするはずです。

同じチャネル名が同じトランザクション内で同じペイロード文字列で複数回シグナリングされる場合、通知イベントの1つのインスタンスのみがリスナーに配信されます。 一方、別個のペイロード文字列を有する通知は、常に別個の通知として配信される。 同様に、異なるトランザクションからの通知が1つの通知に折りたたまれることはありません。 重複通知の後のインスタンスをドロップする場合を除き、NOTIFYは、同じトランザクションからの通知が送信された順序で配信されることを保証します。 また、異なるトランザクションからのメッセージが、トランザクションがコミットされた順序で配信されることも保証される。

NOTIFYを実行するクライアントは、同じ通知チャネル自体でリッスンしているのが一般的です。 その場合、他のすべてのリスニングセッションと同様に、通知イベントが返されます。 アプリケーションのロジックによっては、これにより、データベーステーブルを読み取って、そのセッションが書き出したのと同じ更新を見つけるなど、無駄な作業が発生する可能性があります。 通知セッションのサーバprocessPID (通知イベントメッセージで供給される) が自分自身のセッションsPID (libpqから利用可能) と同じであるかどうかに気付くことによって、このような余分な作業を回避することが可能である。 それらが同じであるとき、通知イベントは跳ね返る自分自身の仕事であり、無視することができる。

概要

NOTIFY channel [ , payload ]

パラメーター

  • channel: シグナリングされる通知チャネルの名前 (任意の識別子) 。

  • payload: 通知とともに通信される「payload」文字列。 これは単純な文字列リテラルとして指定する必要があります。 デフォルト設定では、8000バイトより短くする必要があります。 (バイナリデータまたは大量の情報を通信する必要がある場合は、データベーステーブルに入れてレコードのキーを送信することをお勧めします。)

送信されたが、すべてのリスニングセッションによってまだ処理されていない通知を保持するキューがあります。 このキューがいっぱいになると、NOTIFYを呼び出すトランザクションはコミットで失敗します。 キューは非常に大きく (標準インストールでは8 GB) 、ほぼすべてのユースケースで十分なサイズにする必要があります。 ただし、セッションがLISTENを実行してから非常に長い時間トランザクションに入ると、クリーンアップは実行できません。 キューが半分いっぱいになると、クリーンアップを妨げているセッションを示す警告がログファイルに表示されます。 この場合、クリーンアップを続行できるように、このセッションが現在のトランザクションを終了することを確認する必要があります。

関数pg_notification_queue_usageは、保留中の通知によって現在占有されているキューの一部を返します。

NOTIFYを実行したトランザクションは、2フェーズコミットの準備ができません。

pg_notify

通知を送信するには、関数 (テキスト、テキスト) を使用することもできます。 この関数は、チャネル名を最初の引数とし、ペイロードを2番目の引数とします。 定数以外のチャネル名とペイロードを操作する必要がある場合は、NOTIFYコマンドよりもはるかに使いやすくなります。

listen/notifyシーケンスfrompsqlを設定して実行します。

仮想LISTEN;
    NOTIFYバーチャル;
    PID 8448でサーバープロセスから受信した非同期通知「virtual」。
    仮想、「これはペイロードです」;
    サーバプロセスから受信したペイロード「これはペイロードです」とPID 8448の非同期通知「仮想」。

    聞くfoo;
    SELECT pg_notify('fo' | | 'o', 'pay' | | 'load');
    PID 14728を有するサーバプロセスから受信したペイロード「payload」を有する非同期通知「foo」。