【问题标题】:Postgres deadlock detector not always working?Postgres死锁检测器并不总是有效?
【发布时间】:2015-08-06 11:32:59
【问题描述】:

我们最近在 Posgres 9.4 中遇到了一些死锁问题。 有些查询根本没有返回,只会无限期地挂起。 经过一番调查,我们发现进程死锁似乎是问题所在。当从Lock Monitoring Postgres Wiki 运行查询时,我们会看到一大堆被阻塞的进程。解决它们的唯一方法是开始杀死其中一些进程,直到 Postgres 能够再次解决问题。

现在我的理解是,Postgres 中的死锁检测器应该能够找出存在死锁,然后通过回滚一个被阻止的事务来解决它,以便另一个可以继续,然后重试第一。 但这不是我们的情况,这些进程无限期地陷入僵局,直到我们杀死它们。

deadlock_timeout 设置为 1s(默认值),我找不到打开或关闭死锁检测器的标志,所以我假设它始终打开。

所以我的问题是死锁检测器是否只能检测某些类型的死锁,如果可以,是哪些?

为什么锁监控 Wiki 上显示的查询可以检测到死锁进程,而死锁检测器本身却不能?

【问题讨论】:

  • 如果你真的显示你的锁检查查询的输出会有所帮助

标签: postgresql locking postgresql-9.4


【解决方案1】:

只有当 Postgres 可以看到两个事务在等待对方时,它才会发现死锁。特别是对于两个(或更多)流程,场景必须是:

  • A 需要获取被 B 锁定的资源。
  • B 需要获取被 A 锁定的资源。

死锁处理不会处理如下情况:

  • A需要获取被B锁定的资源。
  • B 在交互式 psql 会话中锁定表,然后取 下午休息,无需提交、回滚或注销。

根据您的描述,听起来您的一个数据库会话没有释放其资源。也许它缺少一个 COMMIT 等。就 Postgres 而言,这不是死锁,因为它知道锁被持有这么长时间是有充分理由的。

您可以做的一件事是设置锁定超时。这意味着进程在放弃并标记问题之前等待尝试获取锁的时间有一个上限。

锁定超时和其他设置记录在: http://www.postgresql.org/docs/9.3/static/runtime-config-client.html

【讨论】:

  • 是的,我怀疑某些资源并没有像您所说的那样释放。所以看起来Postgres的死锁检测器在这里真的没有错,所以我将关闭这个问题。感谢您的帮助!
【解决方案2】:

现在我的理解是,Postgres 中的死锁检测器应该能够找出存在死锁,然后通过回滚一个被阻止的事务来解决它,以便另一个可以继续,然后重试第一个。

只有当死锁发生在 PostgreSQL 后端之间时才会出现这种情况,每个后端都在等待另一个后端。

人们似乎通常希望死锁检测器能够处理死锁也通过应用程序层的情况。事实并非如此。

死锁检测器可以处理这个问题:

  • tx1 锁定表 x 的第 1 行,尝试更新表 x 的第 2 行
  • tx2 锁定表 x 的第 2 行,尝试更新表 x 的第 1 行

不能帮助解决这个问题:

  • 拥有与 tx1 的会话的应用程序线程 A 正在等待来自另一个线程 B 的结果
  • tx1 在打开的事务中锁定表 x 的第 1 行
  • 应用程序线程 B 拥有与 tx2 的会话
  • tx2 正在尝试更新表 x 的第 1 行,tx1 已经拥有该行

这两个都是死锁。 PostgreSQL 只能帮助第一个。它无法知道应用程序的状态是什么,也不知道 tx1 永远无法继续并释放它对 tx2 正在等待的行的锁定,因为拥有它的应用程序线程正在等待 tx2 完成。死锁涉及数据库中的等待和应用程序中的等待,两者都没有完整的情况。

请注意,一个查询等待另一个查询不是死锁。只有在无法打破循环的情况下才会出现死锁,因为没有另一个后端就无法继续前进,而且它们都在互相等待。

您的情况很可能类似于第二种情况,即 应用程序 参与了死锁。

【讨论】:

  • 当您说“拥有与 tx1 的会话的应用程序线程 A 正在等待另一个线程 B 的结果”时,您的意思是我们的应用程序线程正在以某种方式进行通信吗?因为事实并非如此。确实有多个线程(和多个进程),但它们不通信。
  • @rkrzr 在这种情况下,您需要提供表明正在发生死锁的具体数据。我建议使用 \copy (SELECT * FROM pg_stat_activity INNER JOIN pg_locks USING (pid)) WITH (FORMAT CSV, HEADER) 之类的内容,但请注意其中可能包含敏感细节,因此请根据需要进行调整。
  • 很遗憾,我现在无法再重现该问题,但一旦再次出现,我将使用您提供的查询更新此问题。
猜你喜欢
  • 2014-02-20
  • 2016-08-06
  • 2014-06-21
  • 2010-12-28
  • 2018-03-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多