我想更好地理解在postgres中鎖定的機制。涉及外鍵約束的死鎖
假設樹可以有蘋果(通過蘋果桌上的外鍵)。看起來,當選擇一棵樹來更新鎖定是在蘋果上獲得的。但是,即使其他人已經在這個蘋果上持有鎖,該操作也不會被阻止。
這是爲什麼?
p.s.請不要建議刪除「選擇更新」。
方案
Transaction 1 Transaction 2
BEGIN .
update apple; .
. BEGIN
. select tree for update;
. update apple;
. --halts because of the other transaction locking an apple
update apple; .
-- deadlock .
COMMIT
--transaction succeeds
代碼
如果你想嘗試一下在你的Postgres - 這裏是你可以複製代碼/粘貼。
我有以下DB模式
CREATE TABLE trees (
id integer primary key
);
create table apples (
id integer primary key,
tree_id integer references trees(id)
);
和非常簡單的數據
insert into trees values(1);
insert into apples values(1,1);
有兩個簡單的交易。一個是更新蘋果,另一個是鎖定一棵樹並更新一個蘋果。
BEGIN;
UPDATE apples SET id = id WHERE id = 1;
-- run second transaction in paralell
UPDATE apples SET id = id WHERE id = 1;
COMMIT;
BEGIN;
SELECT id FROM trees WHERE id = 1 FOR UPDATE;
UPDATE apples SET id = id WHERE id = 1;
COMMIT;
當我運行它們時 - 死鎖發生在第一次事務的第二次更新時。
ERROR: deadlock detected
DETAIL: Process 81122 waits for ShareLock on transaction 227154; blocked by process 81100.
Process 81100 waits for ShareLock on transaction 227153; blocked by process 81122.
CONTEXT: SQL statement "SELECT 1 FROM ONLY "public"."trees" x WHERE "id" OPERATOR(pg_catalog.=) $1 FOR SHARE OF x"
這是哪一個版本?它看起來不像'ShareLock'在最新版本中使用。第二次交易中需要「更新」嗎? –