デッドロックが起きているかの確認
darknet=# SELECT
l.pid,
l.granted,
d.datname,
l.locktype,
relation,
relation::regclass,
transactionid,
l.mode
FROM
pg_locks l
LEFT JOIN
pg_database d
ON
l.database = d.oid
WHERE
l.pid != pg_backend_pid()
ORDER BY
l.pid
;
実行結果
pid | granted | datname | locktype | relation | relation | transactionid | mode
--------+---------+---------+---------------+----------+-------------------------------+---------------+---------------------
875997 | t | | virtualxid | | | | ExclusiveLock
875997 | t | darknet | relation | 79159 | pg_toast.pg_toast_79156 | | AccessExclusiveLock
875997 | t | darknet | relation | 87560 | 87560 | | AccessExclusiveLock
875997 | t | | transactionid | | | 75407 | ExclusiveLock
875997 | t | darknet | object | | | | AccessShareLock
875997 | t | darknet | relation | 79156 | asn_tab | | AccessExclusiveLock
875997 | t | darknet | relation | 79161 | pg_toast.pg_toast_79156_index | | AccessExclusiveLock
875997 | t | darknet | object | | | | AccessExclusiveLock
875997 | t | darknet | object | | | | AccessExclusiveLock
875997 | t | darknet | object | | | | AccessExclusiveLock
875997 | f | darknet | relation | 66696 | intermediate_flows | | AccessExclusiveLock
875997 | t | | object | | | | AccessShareLock
875997 | t | darknet | relation | 87563 | 87563 | | ShareLock
875997 | t | darknet | relation | 59675 | rib_net_idx | | AccessShareLock
875997 | t | darknet | relation | 87565 | 87565 | | AccessExclusiveLock
875997 | t | darknet | relation | 59669 | rib | | AccessShareLock
pid : プロセスID
granted: boolean, ロックが待ち状態の場合にfalse
あとは、https://www.postgresql.jp/document/9.3/html/view-pg-locks.html を参照
プロセス中の一つの操作で、ロックが待ち状態となっている。
解決方法
根本的な解決ではないが、
SELECT pg_cancel_backend(プロセスID);
でロック待ちを解除できる。
もちろん、データベースを再起動してもできる。その場合の挙動は確認していないので、まずは上記でやってみると良さそう。
筆者はロックがかかるところを特定し、その直前でconn.commit()
したらデッドロックは起こらなくなった。