查询挂在 ClientRead 中并阻止所有其他查询

Kar*_*k T 3 postgresql locking sequelize

这与调试挂起的会话/锁定有关

每隔一段时间(大约一个月 1-2 次)我们就会锁定我们的数据库,因为有一个查询没有完成,并且请求的锁阻塞了所有其他查询。这是我们业务的核心所在,因此会导致停机。

有问题的查询是几个候选之一,所有这些都只是UPDATE在 1 行上运行的simple s。迄今为止我拥有的最好的线索(我对其他途径持开放态度)来自 RDS 性能见解,我看到虽然所有其他查询都锁定在“元组”上,但总是有 1 个查询锁定在“ClientRead”上。根据我的研究,这似乎是 Postgres 等待客户端库向它发送绑定参数或类似的。所以我的理论是,有一个查询有时会随机地以这种状态结束,这会阻止它之后的所有其他查询。这是一个合理的评价吗?

如果是这种情况,我该如何进行调查和解决?我们使用sequelize 5.9.4(node-js)。我们最近确实升级了它,大约 1-2 个月前,所以我想知道这个版本中是否可能存在一个错误,这可能会在处理查询时导致 sequelize 方面的错误,这可能吗?它也可能是一个错误node-postgres,这在我的搜索https://github.com/brianc/node-postgres/issues/1952 中出现

下次发生时,我将尝试使用 RDS 性能洞察的屏幕截图进行更新,其保留时间比预期的要短。

Lau*_*lbe 6

您在事务管理方面有问题。

等待的会话ClientRead完成处理最后一个查询并等待客户端发送下一个请求。这种会话可以阻止任何事情的唯一方法是如果它stateidle in transaction. 所有的锁都被持有直到事务结束,一旦事务完成就不再持有任何锁。

如果会话长时间保持状态idle in transaction,那总是应用程序错误,应用程序忘记结束事务。这很糟糕,不仅因为您观察到的原因,还因为它使 autovacuum 无法完成其基本工作。

您可以做两件事:

  1. 修复应用程序,使其正确关闭事务。这是唯一的好办法。

  2. 通过设置idle_in_transaction_session_timeout使这些事务在一段时间后由 PostgreSQL 自动回滚来防止最坏的情况发生。这将防止无限期地持有锁,但有缺陷的应用程序将收到错误。