【问题标题】:postgresql "idle in transaction" with all locks granted授予所有锁的postgresql“事务中的空闲”
【发布时间】:2021-12-04 01:23:36
【问题描述】:

在一个小表(700 行)上的一个非常简单的删除(按键)时不时地保持“事务空闲”几分钟(通常需要几毫秒),即使所有锁都标记为“已授予”。

我能做些什么来查明是什么原因造成的? 我正在使用这个选择:

  SELECT a.datname,
     c.relname,
     l.transactionid,
     l.mode,
     l.GRANTED,
     a.usename,
     a.waiting,
     a.query, 
     a.query_start,
     age(now(), a.query_start) AS "age", 
     a.pid 
FROM  pg_stat_activity a
 JOIN pg_locks         l ON l.pid = a.pid
 JOIN pg_class         c ON c.oid = l.relation
ORDER BY a.query_start;

它显示了很多“RowExclusiveLock”,但都被授予了......所以我看不出是什么导致了这种延迟高峰。

【问题讨论】:

  • idle in transaction 表示您没有运行commit/rollback/end 或通过事务共享连接到池
  • 事务由 Spring @Transaction 处理,正常工作正常,但时不时保持这种状态几分钟

标签: sql postgresql locking


【解决方案1】:

这是应用服务器的问题。

当应用程序没有以COMMITROLLBACK 结束事务时,会话处于“事务中空闲”状态。这将被视为应用程序中的错误。

在事务结束之前,锁会一直保留(当然是授予的,否则会话不能空闲)。

从 PostgreSQL 9.6 开始,您可以设置参数 idle_in_transaction_session_timeout 以使用 ROLLBACK 自动终止此类事务,但这是避免数据库问题的创可贴,而不是解决方案。

【讨论】:

  • 所以应用程序实际上不可能执行查询? “Idle in transaction”表示查询(删除)已经完成并返回,但事务尚未提交?
  • 是的,完全正确。 SQL 语句已完成,应用程序尚未提交,数据库正在等待事务中的下一条语句。
  • PosGres 没有默认启用自动提交吗?为什么要运行 COMMIT 或 ROLLBACK ?
  • 是的,确实如此。但除非您在某处明确启动事务,否则连接永远不会处于“事务中的空闲”状态。
  • @LaurenzAlbe 这是一篇相当老的帖子,但我们在我们的应用程序中看到了这一点。我们还看到了一些 OOM 错误。应用进程死亡 OOM 是否会导致这些空闲数据库事务?
【解决方案2】:

这也可能是由于:

  1. 连接池耗尽
  2. 交易中的交易
  3. 事务中的隐式 postgres 事务

这篇文章让我对这个问题大开眼界https://www.birdie.care/blog/birdie-engineering-update

这解释了为什么数据库本身没有死锁。只是因为达到了应用的连接池上限。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-05-16
    • 2013-08-28
    • 2012-03-07
    • 2021-07-02
    • 1970-01-01
    • 1970-01-01
    • 2014-04-24
    • 1970-01-01
    相关资源
    最近更新 更多