我想更好地了解一种锁定 postgres 的机制。
假设树可以有苹果(通过苹果表上的外键)。似乎在选择一棵树进行更新锁时是在苹果上获得的。但是,即使其他人已经锁定了这个苹果,操作也不会被阻止。
为什么会这样?
ps 请不要建议删除“选择更新”。
设想
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 中尝试它 - 这是您可以复制/粘贴的代码。
我有以下数据库架构
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"