如何设置 query_timeout 相对于 statement_timeout?

How to set query_timeout in relation to statement_timeout?

我们可以为Client设置2个超时:

我是这样理解的:

问题1是否应该将查询超时设置得比语句超时稍长一些?

我这么认为是因为:

  1. 当一个查询确实耗时过长时,数据库将中止查询并且return将错误发送给客户端
  2. 当应用程序在查询超时时间内没有从服务器获得任何响应时,应用程序将抛出超时错误
    问题2:这可能是什么原因?例如TCP/IP 连接有问题?

交易

我们使用交易的时候是什么情况?
例如当我们查看 example from the docs:

  try {
    await client.query('BEGIN')
    const queryText = 'INSERT INTO users(name) VALUES() RETURNING id'
    const res = await client.query(queryText, ['brianc'])
    const insertPhotoText = 'INSERT INTO photos(user_id, photo_url) VALUES (, )'
    const insertPhotoValues = [res.rows[0].id, 's3.bucket.foo']
    await client.query(insertPhotoText, insertPhotoValues)
    await client.query('COMMIT')
  } catch (e) {
    await client.query('ROLLBACK')
    throw e
  }

所以在快乐路径中,我们调用 query() 5 次:并且每次 query() 调用都会应用 query/statement 超时。
问题 3 所以 BEGIN/COMMIT 查询与 INSERT 查询具有相同的超时,对吗?

在使用 pg-promise 进行了一些测试之后,我得出了这个结论:query-timeout 应该比 statement-timeout

稍长

详情

仅查询超时

  • query-timeout = 10 秒
  • statement-timeout = 未定义

在交易中我们发送 pgsleep(60)(休眠 60 秒)

那么会发生这样的事情:

  • BEGIN 语句被发送到 db
  • 然后pgsleep(60)被发送到数据库
  • 10 秒后我们到达查询超时:node-postgres 将通知 pg-promise
  • pg-promise 将发送 ROLLBACK
    • 由于连接还在执行sleep-60,回滚需要等待
    • 再过 10 秒后,pg-promise 将 return 一个 Query read timeout error
  • 剩余时间数据库会继续执行sleep语句

仅语句超时

  • query-timeout = 未定义
  • statement-timeout = 10 秒

在交易中我们发送 pgsleep(60)(休眠 60 秒)

那么会发生这样的事情:

  • BEGIN 语句被发送到 db
  • 然后pgsleep(60)被发送到数据库
  • 10 秒后数据库将中止休眠,回滚事务并向客户端发回错误:code 57014canceling statement due to statement timeout
  • 应用程序可以处理错误,释放连接

所以我们应该更喜欢得到一个 statement-timeout 并将 query-timeout 设置得稍微长一些,以防数据库无法发回错误(我想这可能是这样的情况,例如网络问题)