У меня есть следующая схема
ID (PK) | REF_ID | ACTIVE | СТАТУС
ID - первичный ключ
Я использую следующий запрос для выбора и обновления
BEGIN;
select * from table where ref_id = $1 and is_active is true for update;
UPDATE table set status = $1 where id =$2;
END;
Объяснение для выше
1) Результат запроса select будет использоваться для блокировки всех строк с предоставленным идентификатором ref, и этот результат используется для некоторой бизнес-логики
2) Обновить запрос для обновления STATUS строки, которая является частью того же ref ID
ВЫПУСКА
postgres@machine ERROR: deadlock detected
postgres@machine DETAIL: Process 28297 waits for ShareLock on transaction 4809510; blocked by process 28296.
Process 28296 waits for ShareLock on transaction 4809502; blocked by process 28297.
Process 28297: select * from jobs where ref_id ='a840a8bd-b8a7-45b2-a474-47e2f68e702d' and is_active is true for update
Process 28296: select * from jobs where ref_id ='a840a8bd-b8a7-45b2-a474-47e2f68e702d' and is_active is true for update
postgres@machine ERROR: deadlock detected
postgres@machine DETAIL: Process 28454 waits for ShareLock on transaction 4810111; blocked by process 28384.
Process 28384 waits for ShareLock on transaction 4810092; blocked by process 28297.
Process 28297 waits for AccessExclusiveLock on tuple (113628,5) of relation 16817 of database 16384; blocked by process 28454.
Process 28454: select * from jobs where ref_id ='a840a8bd-b8a7-45b2-a474-47e2f68e702d' and is_active is true for update
Process 28384: select * from jobs where ref_id ='a840a8bd-b8a7-45b2-a474-47e2f68e702d' and is_active is true for update
Process 28297: select * from jobs where ref_id ='a840a8bd-b8a7-45b2-a474-47e2f68e702d' and is_active is true for update
Эта таблица используется в сильно параллельных и распределенных приложениях (100 параллельно с тем же ref_id), и поэтому я хотел избежать распределенной блокировки, выбрав и обновив в той же транзакции. Но я столкнулся с этой ошибкой взаимоблокировки Не знаю, почему явная блокировка не работает.
Ожидаемое поведение состоит в том, что любая другая работа с таким же ссылочным идентификатором должна ждать, если какая-либо другая работа с таким же ссылочным идентификатором получила блокировку
Помогите мне выяснить, чего мне не хватает или другого обходного пути для этого. Мне все еще не ясно даже после явной блокировки и нахождения в транзакции, почему происходит тупик.