如何设置 query_timeout 相对于 statement_timeout?
How to set query_timeout in relation to statement_timeout?
我们可以为Client设置2个超时:
statement_timeout
:查询语句超时前的毫秒数,默认不超时
query_timeout
查询调用超时前的毫秒数,默认为无超时
我是这样理解的:
statement_timeout
将被传递到数据库(参见 postgres-docs:statement_timeout),当语句花费的时间超过此时间时,数据库将中止查询并 return 一个错误
- 数据库对
query_timeout
一无所知。这由驱动器处理 (node-postgres
)。达到此超时后,node-postgres
将停止侦听响应,但数据库可能仍在执行查询
问题1是否应该将查询超时设置得比语句超时稍长一些?
我这么认为是因为:
- 当一个查询确实耗时过长时,数据库将中止查询并且return将错误发送给客户端
- 当应用程序在查询超时时间内没有从服务器获得任何响应时,应用程序将抛出超时错误
问题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
57014
:canceling statement due to statement timeout
- 应用程序可以处理错误,释放连接
所以我们应该更喜欢得到一个 statement-timeout
并将 query-timeout
设置得稍微长一些,以防数据库无法发回错误(我想这可能是这样的情况,例如网络问题)
我们可以为Client设置2个超时:
statement_timeout
:查询语句超时前的毫秒数,默认不超时query_timeout
查询调用超时前的毫秒数,默认为无超时
我是这样理解的:
statement_timeout
将被传递到数据库(参见 postgres-docs:statement_timeout),当语句花费的时间超过此时间时,数据库将中止查询并 return 一个错误- 数据库对
query_timeout
一无所知。这由驱动器处理 (node-postgres
)。达到此超时后,node-postgres
将停止侦听响应,但数据库可能仍在执行查询
问题1是否应该将查询超时设置得比语句超时稍长一些?
我这么认为是因为:
- 当一个查询确实耗时过长时,数据库将中止查询并且return将错误发送给客户端
- 当应用程序在查询超时时间内没有从服务器获得任何响应时,应用程序将抛出超时错误
问题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
57014
:canceling statement due to statement timeout
- 应用程序可以处理错误,释放连接
所以我们应该更喜欢得到一个 statement-timeout
并将 query-timeout
设置得稍微长一些,以防数据库无法发回错误(我想这可能是这样的情况,例如网络问题)