CodeGym /コース /SQL SELF /現在のクエリとトランザクションの分析

現在のクエリとトランザクションの分析

SQL SELF
レベル 55 , レッスン 4
使用可能

現在のクエリとトランザクションの分析

まずは基本から始めよう。PostgreSQLはSQLクエリやトランザクションを分析するためのすごいツールセットを持ってるんだ。たとえば、組み込み関数の current_query()txid_current() を使えば、こんなことができるよ:

  • 今実行中のSQLクエリを取得できる。
  • どのトランザクションの中でクエリが実行されているか分かる。
  • SQL操作をログに残して、あとで分析できる。
  • トランザクションの問題を追跡できる。たとえば、コードが何かを期待してるのに、実際は全然違うことが起きてる時とか。

こういうのは、普通のデバッグ出力じゃ分からない時や、クエリの動きを「あとから」分析したい時にめっちゃ役立つよ。

組み込み関数のざっくり紹介

current_query() 関数

current_query() は、その接続で今実行されてるSQLクエリのテキストを返してくれる。「なんで分かるの?」って思うかもだけど、PostgreSQLは各接続の状態をちゃんと追跡してて、この関数でその「舞台裏」を覗けるんだ。

シンタックス:

SELECT current_query();

実行例:

-- 関数内でクエリを実行
DO $$
BEGIN
    RAISE NOTICE '現在のクエリ: %', current_query();
END;
$$;

-- 結果:
-- NOTICE: 現在のクエリ: DO $$ BEGIN RAISE NOTICE '現在のクエリ: %', current_query(); END; $$;

この例から分かるように、current_query() は今実行中のクエリのテキストを教えてくれる。複雑なプロシージャを分析する時に超便利!今まさに何が実行されてるか分かるからね。

txid_current() 関数

トランザクションの話になると、txid_current() 関数がめっちゃ役立つ。これは今のトランザクションのユニークなIDを返してくれるんだ。1つのトランザクション内での操作の流れを追いたい時に特に便利!

シンタックス:

SELECT txid_current();

実行例:

BEGIN;

-- 現在のトランザクションIDを取得
SELECT txid_current();

-- 出力例:
-- 564 (例えばこのID)

-- トランザクションを終了
COMMIT;

こういうトランザクションIDはログの突き合わせや、操作の順番の分析、マルチユーザーシステムのデバッグにも使えるよ。

実際のタスクでの使い方例

  1. 実行中のクエリをログに残す。

プロシージャや関数の中にたくさんSQLクエリがある時、どこで何が起きてるか知りたいなら、今のSQLクエリをログに出すのがオススメ。例えば:

DO $$
DECLARE
    current_txn_id BIGINT;
BEGIN
    current_txn_id := txid_current();
    RAISE NOTICE '現在のトランザクションID: %', current_txn_id;

    RAISE NOTICE '現在のクエリ: %', current_query();

    -- ここに他の操作を追加できるよ
END;
$$;

このコードは、トランザクションIDと今のクエリのテキストをコンソールに出してくれる。今何が実行されてるかバッチリ分かるね。

  1. トランザクションの問題を分析する。

例えば、ユーザーから「大量更新でデータが消えた!」ってクレームが来たとしよう。いくつかのプロシージャを1つのトランザクション内で実行してる場合、誰が原因か知りたいよね?こんな感じでやってみよう:

BEGIN;

-- トランザクションのログを追加
DO $$
BEGIN
    RAISE NOTICE '現在のトランザクションID: %', txid_current();
END;
$$;

-- 「問題あり」なSQLクエリを実行
UPDATE orders
SET status = 'processed'
WHERE id IN (SELECT order_id FROM pending_orders);

COMMIT;

もし更新がうまくいかなかったら、どのトランザクションIDで変更しようとしたかすぐ分かる。エラーの特定も簡単だし、トランザクションの競合があったかも分かるよ。

  1. クエリをログに残して履歴を分析する。

今の問題を直すだけじゃなくて、どんなSQLクエリが実行されたか記録しておきたい時もあるよね。例えば、ログ用のテーブルを作って:

CREATE TABLE query_log (
    log_time TIMESTAMP DEFAULT NOW(),
    query_text TEXT,
    txn_id BIGINT
);

こんな感じで current_query()txid_current() を使ってクエリを記録できる:

DO $$
BEGIN
    INSERT INTO query_log (query_text, txn_id)
    VALUES (current_query(), txid_current());
END;
$$;

これで query_log テーブルに、実行されたクエリとそのトランザクションIDが全部残る。データベースの動きを分析するのに超便利!

実践的なケーススタディ

例1: トランザクションの監査

マルチユーザーシステムで操作を分析したい時、トランザクションID(txid_current)をログに残せば、1つのトランザクションごとに操作をグループ化できるよ。

DO $$
DECLARE
    txn_id BIGINT;
BEGIN
    txn_id := txid_current();
    RAISE NOTICE 'トランザクション開始 ID: %', txn_id;

    -- 何かの操作
    UPDATE users SET last_login = NOW() WHERE id = 123;

    RAISE NOTICE '現在のクエリ: %', current_query();
END;
$$;

例2: プロシージャのデバッグを簡単にする

複雑なプロシージャを呼び出して、何かおかしい時。関数のいろんな場所で current_query() のログを仕込めば、どのクエリが実行されたか見えるようになる:

CREATE OR REPLACE FUNCTION debugged_function() RETURNS VOID AS $$
BEGIN
    RAISE NOTICE '更新前の現在のクエリ: %', current_query();
    UPDATE data_table SET field = 'debugging';
    RAISE NOTICE '更新後の現在のクエリ: %', current_query();
END;
$$ LANGUAGE plpgsql;

この関数を呼び出すと、2つの通知でそれぞれのSQLクエリが分かるよ。

使い方のコツ

  1. current_query() を使って、マルチユーザーシステム内でどんなクエリが実行されてるかログに残そう。
  2. txid_current() は、どのタイミングでデータが追加・変更されたか、変更の出どころを分析するのにピッタリ。
  3. 使い終わったら不要なログ出力は消しておこう。RAISE NOTICE で通知を出し続けると、関数の実行が遅くなることもあるからね。

こういう組み込み関数は、データベースの「顕微鏡」みたいなもの。細かい動きを観察できるから、エラーを見つけたり、パフォーマンスを上げたり、複雑なシステムの中で何が起きてるか理解できるようになるよ。PostgreSQLの中では、君のデータベースがもう秘密を教える準備万端。あとは、その読み方を覚えるだけ!

1
アンケート/クイズ
PL/pgSQLデバッグ入門、レベル 55、レッスン 4
使用不可
PL/pgSQLデバッグ入門
PL/pgSQLデバッグ入門
コメント
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION