バッチ処理的に大量のデータ更新を行うためにテーブルロック(EXCLUSIVE MODE)をおこなったのですが、思いがけず問題が発生してロックしたままになってしまいました。
このような時に、解除する方法です。
psqlにてデータベースに接続した後、次のSQLで確認します。
select * from pg_stat_activity;
「waiting」で「t」となっているものがロックしている問合せとなります。
下記の場合、2行目と3行目の「waiting」が「t」です。
ad126z6tmm=> select * from pg_stat_activity;
datid | datname | pid | usesysid | usename | application_name | client_addr | client_hostname | client_port | backend_start | xact_start | query_start | state_change | waiting | state | query
-------+----------+-------+----------+------------+------------------+-------------+-----------------+-------------+-------------------------------+-------------------------------+-------------------------------+-------------------------------+---------+--------+-------------------------------------------------------
16881 | sampledb | 15484 | 17414 | sampleuser | | 127.0.0.1 | | 43766 | 2019-10-01 08:59:27.529876+09 | 2019-10-01 08:59:27.532452+09 | 2019-10-01 09:03:01.699899+09 | 2019-10-01 09:03:01.699899+09 | f | active | SELECT code,price FROM goods WHERE name = $1
16881 | sampledb | 16250 | 17414 | sampleuser | psql | 127.0.0.1 | | 44329 | 2019-10-01 09:00:42.085982+09 | 2019-10-01 09:00:49.732322+09 | 2019-10-01 09:00:49.732322+09 | 2019-10-01 09:00:49.732324+09 | t | active | SELECT count(*) FROM goods WHERE status = 2;
16881 | sampledb | 16629 | 17414 | sampleuser | | 127.0.0.1 | | 44610 | 2019-10-01 09:01:08.860556+09 | 2019-10-01 09:01:08.951878+09 | 2019-10-01 09:01:08.951878+09 | 2019-10-01 09:01:08.95188+09 | t | active | SELECT * FROM goods WHERE type = 10 ORDER BY name ASC
16881 | sampledb | 17217 | 17414 | sampleuser | psql | 127.0.0.1 | | 45036 | 2019-10-01 09:02:38.623184+09 | 2019-10-01 09:03:01.735736+09 | 2019-10-01 09:03:01.735736+09 | 2019-10-01 09:03:01.735738+09 | f | active | SELECT * FROM pg_stat_activity;
(4 rows)
さらに、「backend_start」の時刻を見ると、2行目が先に実行を開始してテーブルをロックしており、3行目が待っている状態でした。
しかしながら、2行目の実行に時間がかかったり、問題があり、ロックしたままになってしまいました。
(なお、「query」のSQLはサンプル的なものに差し替えて掲載しています)
今回は、2行目のロックを解除できれば、待たされている3行目が実行できるようになるはずです。
原因となっている2行目の「pid」を確認すると、「16250」であることが分かります。
ロックの解除は、次のSQLにて実行できます。
SELECT pg_cancel_backend(プロセスID);
今回の場合は、次のようになります。
SELECT pg_cancel_backend(16250);
以上で、無事にロックを解除でき、待たされていた3行目のクエリーも実行されました。
同じような問題が発生した場合のお役に立てれば幸いです。
参考サイト
https://qiita.com/adebadayo/items/2c57084e3b6de01cfc6b