【问题标题】:Transaction time out workaround for PostgreSQLPostgreSQL 的事务超时解决方法
【发布时间】:2012-09-25 12:32:50
【问题描述】:

AFAIK,PostgreSQL 8.3 不支持事务超时。我已经阅读了有关将来支持此功能的信息,并且对此进行了一些讨论。但是,出于特定原因,我需要解决此问题。所以我所做的是一个定期运行的脚本:

1) 根据锁和活动,查询以检索耗时过长的事务的 processID,并保留最旧的 (trxTimeOut.sql):

SELECT procpid
FROM
(
    SELECT DISTINCT age(now(), query_start) AS age, procpid
    FROM pg_stat_activity, pg_locks
    WHERE pg_locks.pid = pg_stat_activity.procpid
) AS foo
WHERE age > '30 seconds'
ORDER BY age DESC
LIMIT 1

2)根据这个查询,杀死对应的进程(trxTimeOut.sh):

psql -h localhost -U postgres -t -d test_database -f trxTimeOut.sql | xargs kill

虽然我已经对其进行了测试并且似乎可行,但我想知道这是否是一种可以接受的方法,还是我应该考虑另一种方法?

【问题讨论】:

  • 是否可以选择至少升级到 8.4 版?如果是这样,您可以使用 pg_terminate_backend() 来终止打开的连接。
  • 感谢您的回答。不幸的是,我不能认为升级是理所当然的(不取决于我)。无论如何, pg_terminate_backend() 只会比 kill 命令更好地结束连接,对吧?我的意思是,查询+杀死(或终止)的解决方案是相对可以接受的?

标签: postgresql transactions timeout


【解决方案1】:

PostgreSQL 从 9.6 版开始提供idle_in_transaction_session_timeout,自动终止空闲时间过长的事务。

还可以通过statement_timeout 设置命令可以花费的时间限制,独立于它所在的事务的持续时间,或者它被卡住的原因(忙查询或等待锁定)。

要自动中止专门等待锁定的事务,请参阅lock_timeout

这些设置可以使用如下所示的SET 等命令在 SQL 级别进行设置,或者可以使用ALTER DATABASE 将这些设置设置为数据库的默认值,或者使用ALTER USER 将这些设置设置为用户,或者通过以下方式设置为整个实例postgresql.conf.

SET statement_timeout=10000;   -- time out after 10 seconds

【讨论】:

  • 谢谢,但问题有点复杂。如果是客户端应用程序。由于某种原因挂起(即与 Java Swing 事件相关,但与花费太长时间的语句无关),这最终可能会阻塞其他客户端,因为第一个客户端已授予一些锁(在未提交/回滚的事务中)第二个正在等待访问。该脚本会终止第一个事务,因为无论问题的根源如何(因此允许第二个客户端继续),花费的时间太长。 statement_timeout 只会中止第二个客户端的事务(因为锁)
  • statement_timeout 没有解决“idle in transaction”状态,这仍然可以防止日志重放。在一些非常具体的情况下,这个答案还不够好。
  • 9.6x 版现在除了statement_timeout 之外还有一个idle_in_transaction_session_timeout 属性。
  • @gregtzar:我已经重写了确实与 PG 8.3 一样过时的答案。感谢您的提醒!
猜你喜欢
  • 2017-04-05
  • 1970-01-01
  • 1970-01-01
  • 2023-03-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-05-27
相关资源
最近更新 更多