什么可能导致“BEGIN”语句“事务空闲”

TmT*_*ron 4 postgresql node.js pg-promise

我们有一个 Node.js 应用程序,它通过 pg-promise 连接到 Postgres 11 服务器 - 所有进程都在 Docker 容器中的单个云服务器上运行。
有时我们会遇到应用程序不再做出反应的情况。

上次发生这种情况时,我花了一点时间通过 pgadmin 检查数据库,它显示连接是idle in transactionwith 语句BEGIN和独占锁virtualxid
在此输入图像描述 在此输入图像描述

我认为情况是这样的:

  1. BEGIN应用程序已通过将sql 命令发送到数据库来启动事务
  2. 数据库收到此命令并启动一个新事务,从而获得模式的排他锁virtualxid
  3. 现在数据库等待应用程序发送下一条语句(直到它收到COMMIT或ROLLBACK) - 然后它将释放模式的排他锁virtualxid
  4. 但由于某种原因,它不再获得语句:
    我认为 node.js 事件循环被阻止 - 因为当时,当我们看到这些锁时,node.js 应用程序不再记录语句。但网络服务器仍然收到请求并报告一些upstream timed out请求。

这有意义吗(我真的不确定2.和3.)?
为什么所有交易一开始都会被阻塞?这只是巧合还是显示的 SQL 可能是错误的?

顺便说一句:在这个答案中,我发现我们可以设置idle_in_transaction_session_timeout,以便这些事务将在超时后被释放 - 这很好,但我尝试了解导致此问题的原因。

Lau*_*lbe 5

交易根本不阻塞。数据库正在等待应用程序发送下一条语句。

事务 ID 上的锁只是事务相互阻塞的一种技术,即使它们没有争用表锁(例如,如果它们正在等待行锁):每个事务都拥有自己的排他锁事务 ID,如果它必须等待并发事务完成,它可以只请求对该事务 ID 的锁定(并被阻止)。

如果所有事务都像这样,那么锁一定位于应用程序中的某个位置;不涉及数据库。

当查找数据库中阻塞的进程时,查找pg_lockswheregranted为 false 的行。