CodeGym /コース /SQL SELF /問題発生時のアラートと通知の設定

問題発生時のアラートと通知の設定

SQL SELF
レベル 46 , レッスン 1
使用可能

みんな、サーバーが落ちたりユーザーの生活が大変になる前に問題を知りたいよね。PostgreSQLには通知を作ったりタスクを実行するためのツールがあるんだ:pg_notifypg_cron。これは、データベース用の目覚まし時計とスケジューラーみたいなものだよ。

例えば、君の通貨交換コースのデータベースで、突然どれかのプロセスが他をブロックしちゃったとしよう。毎回手動で状態をチェックする代わりに、通知を設定しておけばすぐ気付けるよ。データベースの状態を定期的にチェックしたいならpg_cronが便利。これから詳しく見ていこう!

データベースからの即時通知:pg_notify

まずはpg_notifyから。これはPostgreSQLに組み込まれてる関数で、データベースから特定の「チャンネル」に通知を送れるんだ。例えば長いクエリの終了やロックの検出、他のイレギュラーなイベントの通知に使えるよ。

pg_notifyのシンタックスは超シンプル:

NOTIFY <channel>, <message>;
  • channel — 通知を送るチャンネル名。
  • message — 通知のテキスト。

pg_notifyの使い方例を見てみよう。 ロックが検出された時の通知を作ってみるよ:

DO $$
BEGIN
    IF EXISTS (
        SELECT 1
        FROM pg_locks l
        JOIN pg_stat_activity a
        ON l.pid = a.pid
        WHERE NOT l.granted
    ) THEN
        PERFORM pg_notify('alerts', 'データベースでロック発生!');
    END IF;
END $$;

このコードは未処理のロックがあるかチェックして、alertsチャンネルに通知を送るよ。

通知を受け取るには、別の接続でLISTENコマンドを使おう:

LISTEN alerts;

これで、pg_notifyalertsチャンネルにメッセージを送ったら、コンソールに通知が表示されるよ。

例:

NOTIFY alerts, 'おい、ここでロック発生!';

別の接続でLISTEN alertsを実行していたら、すぐにこう表示される:
NOTIFY: おい、ここでロック発生!

pg_notifyはシンプルな通知だけじゃなくて、トリガーと組み合わせてデータ追加・変更・削除の自動通知にも使えるよ:

新しいレコードの通知

CREATE OR REPLACE FUNCTION notify_new_record()
RETURNS trigger AS $$
BEGIN
    PERFORM pg_notify('table_changes', 'テーブルに新しいレコードが追加されたよ!');
    RETURN NEW;
END;
$$ LANGUAGE plpgsql;

CREATE TRIGGER record_added
AFTER INSERT ON your_table
FOR EACH ROW EXECUTE FUNCTION notify_new_record();

これでyour_tableに新しいレコードが追加されるたびに通知が届くよ。

トリガーや組み込み関数については、もうちょっと進んだら詳しくやるからね :P

よくあるミスとその回避法

LISTENを使ってるのに通知が見えない場合は、次をチェックしよう:

  1. 通知を送ってるのと同じ接続で作業してない?
  2. チャンネル名が正しいか確認しよう。
  3. pg_notifyをコミット済みのトランザクション内で呼んでるか確認しよう(COMMIT)。

PostgreSQLのタスクスケジューラー:pg_cron

pg_cronはPostgreSQL用の拡張で、Linuxのクラシックなcronみたいにスケジュールでタスクを実行できるよ。例えば、ロックの定期チェックや統計の収集を自動化できる。

pg_cronでタスクを作成する

pg_cronがインストールされて準備OKなら、毎日logsテーブルの古いレコードを消すタスクを作ってみよう。

SELECT cron.schedule('古いログの削除',
'0 0 * * *',
$$ DELETE FROM logs WHERE created_at < NOW() - INTERVAL '30 days' $$);

これが何をしてるか説明するね:

  • '0 0 * * *' — コマンドの実行スケジュール(毎日0時)。
  • DELETE FROM logs ... — cronが実行するSQLクエリ。

タスクの一覧を見る

pg_cronで実行中のタスクを全部見るには:

SELECT * FROM cron.job;

タスクの無効化

タスクを無効にするには:

SELECT cron.unschedule(jobid);

jobidはタスクのIDで、cron.jobテーブルから確認できるよ。

pg_cronの便利な例

クエリのアクティビティを定期チェック

5分ごとに長時間実行中のクエリをチェックするタスクを作ろう:

SELECT cron.schedule('長いクエリのチェック',
'*/5 * * * *',
$$ SELECT pid, query, state
    FROM pg_stat_activity
    WHERE state = 'active'
        AND now() - query_start > INTERVAL '5 minutes' $$);

このタスクは5分以上実行中のクエリを探してくれるよ。

外部システムとの連携

pg_notifypg_cronも、SlackやTelegram、監視システム(Prometheusとか)と連携できるよ。

Telegram

pg_notifyとTelegramボットを組み合わせて通知を送ることもできる。基本はPythonとかで通知を受け取ってTelegramに転送するスクリプトを書く感じ。

シンプルなPythonボットの例:

import psycopg2
import telegram

# PostgreSQLに接続
conn = psycopg2.connect("dbname=your_database user=your_user")

# Telegramボットを作成
bot = telegram.Bot(token='your_telegram_bot_token')

# 通知をリッスンするためのカーソルを開く
conn.set_isolation_level(psycopg2.extensions.ISOLATION_LEVEL_AUTOCOMMIT)
cur = conn.cursor()
cur.execute("LISTEN alerts;")

# 通知を待ち受け
print("通知を待ってるよ...")
while True:
    conn.poll()
    while conn.notifies:
        notify = conn.notifies.pop()
        print("通知を受信:", notify.payload)
        bot.send_message(chat_id='your_chat_id', text=notify.payload)

これでpg_notify経由の通知をボットが受け取ってくれるよ。

pg_notifypg_cronはいつ使う?

pg_notifyは即時反応が欲しい時(例えばロック発生時に管理者へ通知)に使おう。

pg_cronは定期的なタスク(クエリのアクティビティチェックや古いデータの掃除)に使うのがベスト。

注意点と落とし穴

pg_notifyは即時通知だけど履歴は残らない。ファイルログや外部システムと組み合わせるのがオススメ。

pg_cronはタスクを頻繁に実行しすぎると予想外の負荷になることも。スケジュールに追加する前に必ずクエリをテストしよう。

これでデータベース監視を最適化して管理を自動化する準備はバッチリ!アラートを設定して、ただのSQLプログラマーじゃなくDBAを目指そう!

コメント
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION