単一のトランザクションで、数百万行のデータをテーブル (ユーザー テーブルへの 2 つの外部キーと、それらのキーに関連付けられたインデックスを含む "フォロー" テーブル) にロードしようとしています。最初の試行で、システム メモリが使い果たされたため、スクリプトがクラッシュしました。
調査の結果、クラッシュの原因は外部キー制約によるものであるという結論に達したため、テーブルが空であること (つまり、プロセスが強制終了されたトランザクションが完了していないこと) を確認し、スクリプトを修正して外部キー制約を削除しました。データを挿入するためのキー制約とインデックス。私の意図は、後で制約とインデックスを再作成することでした。
ただし、テーブルが完全に空であるにもかかわらず、テーブルの最初の外部キー制約を削除する ALTER TABLE DROP CONSTRAINT コマンドには非常に長い時間がかかります (数十分)。
私が考えることができる唯一のことは、スクリプトがクラッシュしたために、テーブルに書き込んだ後にコミットしなかった大量のデータに関連しているということです。しかしもちろん、トランザクションはコミットされていないため、データベースにそのデータの痕跡は見つかりません。
このクエリが遅くなる (またはまったく実行されない可能性があります。この記事の執筆時点ではまだ進行中です) 原因は何ですか?また、それを回避するにはどうすればよいですか?
データベースで開いている他のトランザクションがあります (他の非常に大きなテーブルを移行する数時間のトランザクション) が、それらのトランザクションのどれも次のテーブルに触れていません。
編集: pg ロックは以下のとおりです。
db=# select relation::regclass, * from pg_locks where not granted;
-[ RECORD 1 ]------+--------------------
relation | auth_user
locktype | relation
database | 53664
relation | 54195
page |
tuple |
virtualxid |
transactionid |
classid |
objid |
objsubid |
virtualtransaction | 5/343
pid | 17300
mode | AccessExclusiveLock
granted | f
上記の pid (17300) は、単に ALTER TABLE クエリそのものです。他のロックはなく、ロックを待っているプロセスもありません。