同じUPDATE
クエリを次のように2回実行しようとしました。外部キー制約付きローの更新でロックする
トランザクションが初めてロックされていませんが、2番目のクエリの後に行ロックが表示されます。
スキーマ:
test=# \d t1
Table "public.t1"
Column | Type | Collation | Nullable | Default
--------+---------+-----------+----------+---------
i | integer | | not null |
j | integer | | |
Indexes:
"t1_pkey" PRIMARY KEY, btree (i)
Referenced by:
TABLE "t2" CONSTRAINT "t2_j_fkey" FOREIGN KEY (j) REFERENCES t1(i)
test=# \d t2
Table "public.t2"
Column | Type | Collation | Nullable | Default
--------+---------+-----------+----------+---------
i | integer | | not null |
j | integer | | |
k | integer | | |
Indexes:
"t2_pkey" PRIMARY KEY, btree (i)
Foreign-key constraints:
"t2_j_fkey" FOREIGN KEY (j) REFERENCES t1(i)
既存のデータ:
test=# SELECT * FROM t1 ORDER BY i;
i | j
---+---
1 | 1
2 | 2
(2 rows)
test=# SELECT * FROM t2 ORDER BY i;
i | j | k
---+---+---
3 | 1 |
4 | 2 |
(2 rows)
UPDATEクエリと行ロックのステータス:
test=# BEGIN;
BEGIN
test=# UPDATE t2 SET k = 123 WHERE i = 3;
UPDATE 1
test=# SELECT * FROM t1 AS t, pgrowlocks('t1') AS p WHERE p.locked_row = t.ctid;
i | j | locked_row | locker | multi | xids | modes | pids
---+---+------------+--------+-------+------+-------+------
(0 rows)
test=# UPDATE t2 SET k = 123 WHERE i = 3;
UPDATE 1
test=# SELECT * FROM t1 AS t, pgrowlocks('t1') AS p WHERE p.locked_row = t.ctid;
i | j | locked_row | locker | multi | xids | modes | pids
---+---+------------+--------+-------+----------+-------------------+------
1 | 1 | (0,1) | 107239 | f | {107239} | {"For Key Share"} | {76}
(1 row)
test=#
Postgresが唯一の二度目に行ロックを取得しようとしないのはなぜ?
ちなみに、クエリ更新列t2.jは、t1行の新しいロック(ForKeyShare)を一度に作成します。この動作は、t2.jに外部キー制約の参照t1.iがあるので意味があります。しかし、上記の質問はそうではないようです。
誰でもこのロックについて説明できますか?
PostgreSQLのバージョン:9.6.3
なぜROW SHAREロックが問題だと思いますか? –
ロックの競合が原因で不要なロックのパフォーマンスが低下し、私の場合はデッドロックが発生しています。もちろん、あるトランザクションで同じ行にある複数のUPDATEがうまくいかず、明示的なロックを使用するとデッドロックの危険性を減らすことができます。私の場合、デッドロックはTPC-Cのパフォーマンステストが自分で作成されていないと起こりました。 PostgreSQLだけがこのように動作する理由を知りたかったのです。 – 38kun
T1の行共有は、その行の更新(または選択)を妨げません。その行のDELETEのみを防止します。だから私はそれがどのようにデッドロックにつながるのか理解していない。プラスデッドロックは、データベース内の問題ではなく、_application_でのトランザクション処理の誤りの兆候です。しかし、推論や技術的な詳細を知りたければ、[postgresメーリングリスト](https://www.postgresql.org/list/pgsql-general/)でこれを尋ねてください。 –