我将要翻译的内容如下:
我有以下数据库表结构:
ID (PK)| REF_ID | ACTIVE | STATUS
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)选择查询结果将用于锁定所有具有提供的引用ID的行,并且该结果将用于某些业务逻辑。
2)更新查询以更新与同一引用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),因此我希望通过在同一事务中进行选择和更新来避免分布式锁。但是,我遇到了死锁错误,我不知道为什么显式锁定没有起作用。
期望的行为是,如果其他任何具有相同引用ID的作业已获取锁,则任何其他具有相同引用ID的作业必须等待。
请帮助我找出我错过了什么或另一个解决方法。即使进行了显式锁定并且在事务内部,我仍然不清楚为什么会发生死锁。
ORDER BY
放入SELECT ... FOR UPDATE
中。除此之外,在高并发应用程序中,当许多行在一个事务中被锁定时,死锁是无法避免的。 - Laurenz Albe