如何处理idle_in_transaction_session_timeout?

问题描述 投票:0回答:1

当我们设置 idle_in_transaction_session_timeout(超时)数据库会终止空闲一段时间的连接。这和预期的一样,但是我想知道我们应该如何在应用程序代码中处理这种情况。我们使用pg-promise 10.3.1.

详情 的测试。

  • 我们将连接池的大小设置为 1因此,我们只有一个会话
  • 我们将闲置交易会话超时设置为 2.5 秒。SET idle_in_transaction_session_timeout TO 2500
  • 现在我们开始交易,并睡上一觉 5 秒钟
  • 之后 2.5秒,数据库将终止会话,并向客户端发送一个错误信息。pgp-error error: terminating connection due to idle-in-transaction timeout
  • 在另一个... 2.5秒,事务代码尝试发送一个查询(通过已经终止的会话),结果如预期的那样失败了,然后pg-promise会尝试回滚事务,也会失败(我猜也是预期的)。dbIdle failed Error: Client has encountered a connection error and is not queryable
    • 然后pg-promise会尝试回滚事务,这也会失败(我猜也是预料之中的)。
  • 但现在我们开始一个新的查询,这个查询也失败了。dbCall failed Client has encountered a connection error and is not queryable
    • 这是预料之中的吗?我希望pg-promise能以某种方式从池子中移除 "中断 "的连接,这样我们就能得到一个新的连接。
    • 显然不是这样,那么我们应该如何处理这种情况:即如何恢复,以便我们能够向数据库发送新的查询?

代码示例:

import pgPromise, { IMain } from "pg-promise";
import * as dbConfig from "./db-config.json";
import { IConnectionParameters } from "pg-promise/typescript/pg-subset";

const cll = "pg";
console.time(cll);

const pgp: IMain = pgPromise({
  query(e) {
    console.timeLog(cll,`> ${e.query}`);
  },
  error(e, ctx) {
    console.timeLog(cll,"pgp-error", e);
  }
});

const connectParams: IConnectionParameters = {
  ...dbConfig,
  application_name: "pg-test",
  max: 1
};
const db = pgp(connectParams);

/**
 * @param timeoutMs 0 is no timeout
 */
async function setDbIdleInTxTimeout(timeoutMs: number = 0) {
  await db.any("SET idle_in_transaction_session_timeout TO $1;", timeoutMs);
}

async function dbIdle(sleepTimeSec: number) {
  console.timeLog(cll, `starting db idle ${sleepTimeSec}`);
  const result = await db.tx(async t => {
    await new Promise(resolve => setTimeout(resolve, sleepTimeSec * 1000));
    return t.one("Select $1 as sleep_sec", sleepTimeSec);
  });
  console.timeLog(cll, result);
}

async function main() {
  await setDbIdleInTxTimeout(2500);
  try {
    await dbIdle(5);
  } catch (e) {
    console.timeLog(cll, "dbIdle failed", e);
  }
  try {
    await db.one("Select 1+1 as res");
  } catch (e) {
    console.timeLog(cll, "dbCall failed", e);
  }
}

main().finally(() => {
  pgp.end();
});

控制台出线t(删除了一些无用的行)。

"C:\Program Files\nodejs\node.exe" D:\dev_no_backup\pg-promise-tx\dist\index.js
pg: 23.959ms > SET idle_in_transaction_session_timeout TO 2500;
pg: 28.696ms starting db idle 5
pg: 29.705ms > begin
pg: 2531.247ms pgp-error error: terminating connection due to idle-in-transaction timeout
    at TCP.onStreamRead (internal/stream_base_commons.js:182:23) {
  name: 'error',
  severity: 'FATAL',
  code: '25P03',
}
pg: 2533.569ms pgp-error Error: Connection terminated unexpectedly
pg: 5031.091ms > Select 5 as sleep_sec
pg: 5031.323ms pgp-error Error: Client has encountered a connection error and is not queryable
pg: 5031.489ms > rollback
pg: 5031.570ms pgp-error Error: Client has encountered a connection error and is not queryable
pg: 5031.953ms dbIdle failed Error: Client has encountered a connection error and is not queryable
pg: 5032.094ms > Select 1+1 as res
pg: 5032.164ms pgp-error Error: Client has encountered a connection error and is not queryable
pg: 5032.303ms dbCall failed Error: Client has encountered a connection error and is not queryable

Process finished with exit code 0
pg-promise
1个回答
0
投票

这个 第680期 已在pg-promise中得到修正 10.3.5

© www.soinside.com 2019 - 2024. All rights reserved.