Как имитировать взаимоблокировку в PostgreSQL?

Я новичок в PostgreSQL. Я хочу имитировать тупик для этого расписания: enter image description here

как имитировать взаимоблокировку в PostgreSQL? Возможно ли это вообще? Как заблокировать конкретный столбец?
EDIT:

    BEGIN;
UPDATE deadlock_demonstration
SET salary1=(SELECT salary1 
FROM deadlock_demonstration
WHERE worker_id = 1 
FOR UPDATE)+100
WHERE worker_id=1;
SELECT pg_sleep(5);
commit;
SELECT salary2 FROM deadlock_demonstration WHERE worker_id = 1 FOR UPDATE;

на другом экране я запустил это

    BEGIN;
UPDATE deadlock_demonstration
SET salary2=(SELECT salary1 
FROM deadlock_demonstration
WHERE worker_id = 1
FOR UPDATE)+200
WHERE worker_id=1;
SELECT pg_sleep(5);
commit;
SELECT salary1 FROM deadlock_demonstration WHERE worker_id = 1 FOR UPDATE;

почему тупик не происходит? Можете ли вы дать предложение, что я должен изменить, чтобы стимулировать тупик?

2 ответов


  1. открыть два соединения параллельно, как два экземпляра psql или два окна запросов в pgAdmin (каждый имеет свой собственный сеанс).
  2. запуск транзакции в каждом соединении. BEGIN;
  3. запуск взаимно конфликтующих команд по очереди.
  4. прежде чем вы сможете зафиксировать, один из двух будет откат с исключением взаимоблокировки.
  5. вы можете откатить другой. ROLLBACK;

явно замок таблицы так же просто, как:

LOCK tbl;

блокировка строк может быть выполнена с помощью:

SELECT * FROM tbl WHERE boo = 3 FOR UPDATE;

или FOR SHARE etc. подробности в инструкции здесь.

пример

ваш добавленный пример не может взаимоблокировки. Сначала оба пытаются взять одну и ту же блокировку в одной и той же строке одной и той же таблицы. Второй будет ждать, пока первый закончит.

пример для фактического создания взаимоблокировки (строки должны существовать или блокировка не будет принято):

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 внес этот скриншот после проверки моего решения:

enter image description here


означает ли это, что произошел тупик?

нет. Это значит, что он говорит, Вы не можете использовать commit в список pgsql, ясно сказано здесь.