如何在语句超时时设置查询超时时间?

8
我们可以为Client设置2个超时时间:
- statement_timeout:查询中语句超时的毫秒数,默认没有超时时间。 - query_timeout:查询调用超时的毫秒数,默认没有超时时间。
我这样理解:
- statement_timeout会传递给数据库(参见postgres-docs:statement_timeout),当一条语句执行的时间超过了这个时间,数据库将终止查询并返回错误。 - 数据库不知道query_timeout的任何信息。这由驱动程序(node-postgres)处理。当达到此超时时间时,node-postgres将停止等待响应,但是数据库可能仍在执行查询。 问题1:我们应该将查询超时时间设置得比语句超时时间稍长吗?
我认为应该,因为这样做有以下好处:
- 当一个查询真正花费太长时间时,数据库将终止查询并返回错误。 - 如果应用程序在查询超时时间内未收到来自服务器的响应,则应用程序会抛出超时错误。 问题2:这可能是什么原因?例如TCP/IP连接有问题吗?
这可能是由于网络问题、服务器负载过高或其他一些原因导致的。

事务

我们在什么情况下使用事务?
例如文档中的示例
  try {
    await client.query('BEGIN')
    const queryText = 'INSERT INTO users(name) VALUES($1) RETURNING id'
    const res = await client.query(queryText, ['brianc'])
    const insertPhotoText = 'INSERT INTO photos(user_id, photo_url) VALUES ($1, $2)'
    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()都会应用查询/语句超时。
问题3 那么BEGIN/COMMIT查询的超时时间和INSERT查询的超时时间一样吗?


请参见node-postgres中有关编程的相关问题。 - TmTron
1个回答

9
经过使用pg-promise进行一些测试后,我得出结论:query-timeout应该略长于statement-timeout。
细节:
1. 仅使用query-timeout
- query-timeout = 10秒 - statement-timeout = undefined
在事务中,我们发送pgsleep(60)(睡眠60秒)
然后会发生以下情况:
- 发送BEGIN语句到数据库 - 然后将pgsleep(60)发送到数据库 - 在10秒钟后,我们达到了查询超时时间:node-postgres将通知pg-promise - pg-promise将发送ROLLBACK - 由于连接仍在执行sleep-60,回滚将不得不等待 - 另外10秒后,pg-promise将返回“Query read timeout error” - 数据库将继续执行剩余的睡眠语句。
2. 仅使用statement-timeout
- query-timeout = undefined - statement-timeout = 10秒
在事务中,我们发送pgsleep(60)(睡眠60秒)
然后会发生以下情况:
- 发送BEGIN语句到数据库 - 然后将pgsleep(60)发送到数据库 - 10秒后,数据库将中止睡眠,回滚事务并向客户端发送错误:code 57014:“canceling statement due to statement timeout” - 应用程序可以处理错误,连接被释放。
因此,我们应该更喜欢获取一个statement-timeout并将query-timeout设置得稍微长一些,以防万一数据库无法返回错误(例如在存在网络问题的情况下)。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接