-
psql
の2つのインスタンスのように、2つの接続を並行して開きます またはpgAdminの2つのクエリウィンドウ(それぞれに独自のセッションがあります)。 - 各接続でトランザクションを開始します。
BEGIN;
- 相互に競合するコマンドを順番に実行します。
- コミットする前に、2つのうちの1つがデッドロック例外でロールバックされます。
- もう一方をロールバックすることをお勧めします。
ROLLBACK;
明示的に
LOCK tbl;
行のロックは次の方法で実行できます:
SELECT * FROM tbl WHERE boo = 3 FOR UPDATE;
またはFOR SHARE
など。
(またはUPDATE
を使用して暗黙的に またはDELETE
。)
例
追加した例はデッドロックできません。どちらも、最初に同じテーブルの同じ行で同じロックを取得しようとします。 2番目は最初が終了するのを待ちます。
実際にデッドロックを生成する例(行が存在する必要があります。存在しない場合、ロックは取得されません):
Transaction 1 Transaction 2
BEGIN;
BEGIN;
SELECT salary1
FROM deadlock_demonstration
WHERE worker_id = 1
FOR UPDATE;
SELECT salary1
FROM deadlock_demonstration
WHERE worker_id = 2
FOR UPDATE;
UPDATE deadlock_demonstration
SET salary1 = 100
WHERE worker_id = 2;
UPDATE deadlock_demonstration
SET salary1 = 100
WHERE worker_id = 1;
--> ... 💣 deadlock!
結果
OP user3388473は、ソリューションを確認した後、このスクリーンショットを提供しました: