Я хотел бы лучше понять механизм блокировки в 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 Schema
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' используется в последней версии. Требуется ли 'UPDATE' во второй транзакции? –