如何在Postgres中调试ShareLock

jab*_*lab 9 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"
Run Code Online (Sandbox Code Playgroud)

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

我想知道如何最好地调试这样的问题给定这些约束和事实上每个单独的锁是相对短暂的(通常1000-2000ms).

我尝试过的事情:

  • 监控pg_locks(并加入pg_class上下文).
  • 调查pageinspect.
  • 手动和本地复制本地pgbench都有超级用户权限.到目前为止,我无法在本地复制该问题(我怀疑由于数据集要小得多,但我无法确定).

值得一提的是,CPU利用率出现高(的平均负载> 1),当我看到这些问题,所以它可能有什么不对上述本身和我看到它的系统资源不足是可用的结果.我仍然想了解如何最好地调试它,所以我可以理解究竟发生了什么.

Cra*_*ger 19

关键是它是交易的ShareLock .

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

这时候等待的事务(或多个)正试图通常发生在INSERT一个UNIQUEPRIMARY KEY值由等待上交易改性地区最近插入的行/.等待事务无法继续,直到他们知道等待事务的结果 - 无论是已提交还是已回滚,以及是否已提交,是否已删除/插入目标行/等等.

这与您的错误消息中的内容一致.proc"x"试图插入"my_test_table"并且必须等到proc"y"提交xact"z"以确定是否引发了一次独特的违规或是否可以继续.

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

  • |||| |||| |||| ||||| || <-- “克雷格·林格再次拯救了我”计数。 (6认同)