两个并发但相同的DELETE语句会导致死锁吗?

pbi*_*len 8 sql postgresql database-deadlocks postgresql-9.5

假设some_table有两行,主键12.以下语句序列可能导致死锁:

session 1: begin;
session 2: begin;
session 1: DELETE FROM my_table WHERE my_key = 1;
session 2: DELETE FROM my_table WHERE my_key = 2;
session 1: DELETE FROM my_table WHERE my_key = 2;
session 2: DELETE FROM my_table WHERE my_key = 1;
Run Code Online (Sandbox Code Playgroud)

如果两个会话以相同的顺序删除,则不会发生死锁.

现在,回答我的问题,如果DELETE语句触及多行会发生什么?例如:

session 1: begin;
session 2: begin;
session 1: DELETE FROM my_table;
session 2: DELETE FROM my_table;
Run Code Online (Sandbox Code Playgroud)

是否有可能两个并发但相同的DELETE语句将以不同的顺序删除行?是否可以强制执行删除顺序以避免死锁?

我在文档中找不到这些信息,所以我想说不能保证删除顺序(尽管它可能间接地作为实现细节).我想在这里仔细检查一下.

Lau*_*lbe 1

是的,这可能会导致死锁,因为表中的行顺序不固定。

AnyUPDATE可能会更改顺序表扫描返回的行的顺序,并且如果synchronize_seqscans是其默认值on,则即使表不会更改,如果同时执行多个顺序扫描(如您的情况),顺序也可能会更改。

您应该首先运行SELECT ... FOR UPDATEwith anORDER BY子句以降低死锁的风险,但即使这样您也不能绝对确定,除非您按不会同时更新的列(如主键)进行排序。

  • 摘要:“DELETE FROM my_table WHERE my_key IN (SELECT my_key FROM my_table ORDER BY my_key FOR UPDATE (SKIP LOCKED/NOWAIT)”应该给出确定性的删除顺序。如果需要,可以添加“SKIP LOCKED”或“NOWAIT”。 (2认同)