pg_activityで刺さっているクエリを殺す

サービス運用しているとクエリが刺さってパフォーマンスが悪くなってしまっているとき、ありますよね。根本対応は別途やるとして、今はひとまずこの刺さっているクエリを殺して凌ぎたい。PostgreSQLではpg_stat_activityというテーブルに現在実行中の情報が入っています。

SQLで殺してもいいですが、同僚に教えてもらったpg_activityというツールが便利だったのでメモしておきます。

cliのツールですが、tigなどと同じような形で現在実行中の中から殺したいクエリを選んで、というのを視覚的に行なえるので便利です。

インストール

pg_activityはPythonで書かれているツールなので、pipでインストールします。ansibleでインストールしているので、以下のように書きました。amazon linux2上での動作を確認していますが、他でも似たようにやれば動くと思います。

---
- tasks:
    - name: "yum install"
      yum: name={{item}} state=installed
      with_items:
        - gcc
        - postgresql
        - postgresql-devel
        - python3
        - python3-pip
        - python3-devel
      become: true
    - name : install pg_activity
      shell: pip3 install pg_activity
      become: true

pg_activityを動かしてみる

こんな感じで動かせます。

% pg_activity --username=my_user_name --host=my_rds_host --dbname=my_db_name --rds

殺したいクエリがいたら、それを選択してkを押すと殺せます。

試してみる

意図的にですが、クエリを殺す例をやってみます。ターミナルAでトランザクションを張って、テーブルをロックしてみます。

go-active-learning=> BEGIN;
BEGIN
go-active-learning=> LOCK TABLE example IN EXCLUSIVE MODE;
LOCK TABLE

別のターミナルBで更新系のクエリを発行してみます。そうするとまあ当然ブロックされる。

go-active-learning=> BEGIN;
BEGIN
go-active-learning=> UPDATE example SET label = 1 where id = 8508;

この状態でpg_activityを見にいくとこんな状態になっていることが分かります。

この状態でUPDATE ...を選択してkを押すとこのクエリを殺せます。ターミナルBでは無慈悲なメッセージが流れていて、殺せていることが分かります。

go-active-learning=> UPDATE example SET label = 1 where id = 8508;
FATAL:  terminating connection due to administrator command
LINE 1: UPDATE example SET label = 1 where id = 8508;
               ^
SSL connection has been closed unexpectedly
The connection to the server was lost. Attempting reset: Succeeded.

クエリが刺さらないのが一番ですが、もし刺さってしまったときにどう対処すればいいか押さえておくと安心できますね。

10年戦えるデータ分析入門 SQLを武器にデータ活用時代を生き抜く (Informatics &IDEA)

10年戦えるデータ分析入門 SQLを武器にデータ活用時代を生き抜く (Informatics &IDEA)