【问题标题】:Can two concurrent but identical DELETE statements cause a deadlock?两个并发但相同的 DELETE 语句会导致死锁吗?
【发布时间】:2019-01-28 21:20:49
【问题描述】:

假设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;

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

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

session 1: begin;
session 2: begin;
session 1: DELETE FROM my_table;
session 2: DELETE FROM my_table;

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

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

【问题讨论】:

  • 这将导致死锁,因为您没有提交任何事务。
  • @Ben AFAIK 在DELETE 语句期间可能会发生死锁(即尽可能早)。它不应该延迟到COMMIT 声明,这里确实没有。我的问题不是因为没有COMMIT 声明而导致的微不足道的僵局。
  • “事务”确实会导致访问“序列化”。它保证所有处理都将成功完成,否则将失败。它还将阻止等待访问相同资源的事务中使用的资源。您要做的第一件事是获取并锁定完成当前事务步骤所需的资源。在您的情况下,锁定您想要的所有行(选择更新)或锁定表,访问行并释放它。说真的,最简单的方法是在每个事务中以相同的顺序访问资源,以防止“死锁”。
  • @RyanVincent 这实际上是我的问题。如果行总是以相同的顺序删除,或者如果有一种方法可以强制删除顺序,则 SELECT FOR UPDATE 之前的 DELETE 将是不必要的。如果没有,SELECT ... ORDER BY ... FOR UPDATE (SKIP LOCKED) 确实很有用。
  • 关于FOR UPDATE,我不确定这是否如我们预期的那样有效。见stackoverflow.com/questions/51972202/…

标签: sql postgresql postgresql-9.5 database-deadlocks


【解决方案1】:

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

任何UPDATE 都可能更改顺序表扫描返回的行的顺序,如果synchronize_seqscans 为其默认值on,则即使在多次顺序扫描时该表没有变化,顺序也可能发生变化同时执行(就像你的情况一样)。

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

【讨论】:

  • 谢谢,这是我的预期。关于添加ORDER BY,您的意思是这样的:DELETE FROM my_table WHERE my_key IN (SELECT my_key FROM my_table ORDER MY my_key)DELETE 是否遵守子查询的顺序?
  • 我想得不够努力;我编辑了答案。之前的 SELECT ... FOR UPDATE 应该可以解决问题。
  • 太棒了!这也是我的想法,所以我创建了stackoverflow.com/questions/51972202/…
  • 总结:DELETE FROM my_table WHERE my_key IN (SELECT my_key FROM my_table ORDER BY my_key FOR UPDATE (SKIP LOCKED/NOWAIT) 应该给出一个确定的删除顺序。如果需要,可以添加SKIP LOCKEDNOWAIT
  • 应该可以,只是NOWAIT 会导致错误。
猜你喜欢
  • 1970-01-01
  • 2021-11-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多