如何在Postgres中调试ShareLock

时间:2017-09-19 15:09:30

标签: postgresql

我在Postgres服务器日志中看到了以下几种情况:

LOG:  process x still waiting for ShareLock on transaction y after 1000.109 ms 
DETAIL:  Process holding the lock: z. Wait queue: x.
CONTEXT:  while inserting index tuple (a,b) in relation "my_test_table"
    SQL function "my_test_function" statement 1 
...
LOG:  process x acquired ShareLock on transaction y after 1013.664 ms
CONTEXT:  while inserting index tuple (a,b) in relation "my_test_table"

我正在运行Postgres 9.5.3 。另外我在Heroku上运行所以我无法访问细粒度的超级用户调试工具。

我想知道在给定这些约束的情况下如何最好地调试这样的问题以及每个锁相对瞬态(通常为1000-2000ms)的事实。

我尝试过的事情:

  • 监控libspatialite(并加入pg_locks了解相关情况)。
  • 调查pg_class
  • 手动和pageinspect本地复制,我有超级用户权限。到目前为止,我无法在本地复制该问题(我怀疑,因为数据集要小得多,但我无法确定)。

值得注意的是,当我看到这些问题时,CPU利用率看起来很高(负载平均值> 1),因此上述本身可能没有任何问题,并且我看到了它由于系统资源不足而导致。我仍然想了解如何最好地调试它,所以我可以理解到底发生了什么。

1 个答案:

答案 0 :(得分:16)

关键是它是交易上的ShareLock。

这意味着一个事务正在等待另一个事务提交/回滚,然后才能继续。它只是松散地锁定"。这里发生的是PostgreSQL事务在启动时对其自己的事务ID采用ExclusiveLock。其他想要等待它完成的事务可以尝试获取事务上的ShareLock,这将阻塞,直到在提交/中止时释放ExclusiveLock。它基本上使用锁定机制作为实现事务间完成信令的便利。

这通常发生在等待的交易尝试INSERT UNIQUEPRIMARY KEY值的最近由等待的行插入/修改的行时 - 在交易上。等待事务无法继续,直到他们知道等待事务的结果 - 无论是已提交还是已回滚,以及是否已提交,目标行是否已删除/插入/等等。

这与您的错误消息中的内容一致。 proc" x"正试图插入" my_test_table"并且必须等到proc" y"提交xact" z"了解是否提出独特的违规行为或是否可以继续进行。

很可能你在某种upsert或队列处理系统中存在争用。如果你有一些函数/事务模式尝试插入到一个竞争激烈的表中,然后在提交之前做了很多其他耗时的工作,也会发生这种情况。