PostgreSQL中有许多个timeout,逐个弄懂它们的含义和使用

文摘   科技   2024-10-11 09:33   北京  


我是【Sean】, 微信: _iihero,  欢迎大家长按关注并加星公众号:数据库杂记。有好资源相送,同时为你提供及时更新。已关注的朋友,发送0、1到7,都有好资源相送。

为方便交流,建了一个数据库相关的群: 数据库Hacker,现在还可以扫码入群。欢迎对这个领域有兴趣的朋友扫码入群。


1、deadlock_timeout

Sets the time to wait on a lock before checking for deadlock

这是进行死锁检测之前在一个锁上等待的时间量。死锁检测相对昂贵,因此服务器不会在每次等待锁时都运行这个它。 我们乐观地假设在生产应用中死锁是不常出现的,并且只在开始检测死锁之前等待一会儿。增加这个值就减少了浪费在无用的死锁检测上的时间,但是减慢了报告真正死锁错误的速度。 如果指定值时没有单位,则以毫秒为单位。默认是 1 秒1s),这可能是实际中你想要的最小值。 在一个高负载的服务器上,你可能需要增大它。这个值的理想设置应该超过你通常的事务时间,这样就可以减少在锁释放之前就开始死锁检查的机会。只有超级用户可以更改这个设置。

2、lock_timeout (+ v9.3)

Sets the maximum allowed duration of any wait for a lock: 等待一个锁的最长时间

如果任何语句在试图获取表、索引、行或其他数据库对象上的锁时等到超过指定的时间量,该语句将被中止。 该时间限制独立地应用于每一次锁获取尝试。该限制会应用到显式锁定请求(如LOCK TABLE或不带NOWAIT的SELECT FOR UPDATE)和隐式获得的锁。 如果指定值时没有单位,则以毫秒为单位。一个零值(默认)将禁用超时。

与statement_timeout不同,这个超时只在等待锁时发生。注意如果statement_timeout为非零,设置lock_timeout为相同或更大的值没有意义,因为事务超时将总是第一个被触发。 如果log_min_error_statement 被设置为ERROR 或更低,超时的语句将被记录。

3、statement_timeout

Sets the maximum allowed duration of any statement: 任何SQL语句的最长允许时间。

中止任何使用了超过指定时间量的语句。 如果log_min_error_statement被设置为ERROR或更低,语句如果超时也会被记录。 如果指定值时没有单位,则以毫秒为单位。一个零值(默认)将禁用超时。

超时从命令到达服务器的时间开始计算,一直到它被服务器完成为止。 在扩展查询协议中,当任何与查询相关的消息(解析、绑定、执行、描述)到达时,超时就开始运行,并且可以通过执行完成或同步消息来取消超时。

我们不推荐在postgresql.conf中设置statement_timeout,因为它会影响所有会话。

4、authentication_timeout

Sets the maximum allowed time to complete client authentication

允许完成客户端认证的最长时间。如果一个客户端没有在这段时间里完成认证协议,服务器将关闭连接。 这样就避免了出问题的客户端无限制地占有一个连接。如果指定值时没有单位,则以秒为单位。 默认值是 1分钟(1m)。这个参数只能在服务器命令行上或者在postgresql.conf文件中设置。

5、tcp_user_timeout (+v12)

指定传输的数据在TCP连接被强制关闭之前可以保持未确认状态的时间量。 如果指定值时没有单位,则以毫秒为单位。值0(默认值)表示选择操作系统默认值。 这个参数只有在支持TCP_USER_TIMEOUT的系统上才被支持;在其他系统上,它必须为零。 在通过Unix-domain 套接字连接的会话中,此参数将被忽略并且始终读取为零。

在Windows上不支持该参数,并且必须为零。

6、idle_session_timeout (+v14)

Sets the maximum allowed idle time between queries, when not in a transaction

终止任何超过指定的时间的空闲会话(即等待客户端查询),但不是在打开的事务中。如果该值没有指定单位,则以毫秒为单位。零值(默认值) 禁用超时。

与开放事务的情况不同,没有事务的空闲会话不会给服务器带来很大的成本,因此与idle_in_transaction_session_timeout相比,启用此超时的需求更少。

在通过连接池软件或其他中间件建立的连接上强制执行此超时时要小心,因为这样的层可能无法很好地响应意外的连接关闭。仅对交互式会话启用此超时可能会有所帮助,也许可以将其仅应用于特定用户。

一个小示例:

直接设置系统参数, 设置为20秒空闲连接超时

postgres=# alter system set idle_session_timeout=20000;
ALTER SYSTEM
postgres=# show idle_session_timeout ;
idle_session_timeout
----------------------
0
(1 row)

postgres=# select pg_reload_conf();
pg_reload_conf
----------------
t
(1 row)

postgres=# show idle_session_timeout ;
idle_session_timeout
----------------------
20s
(1 row)

然后在另一个会话里头:

postgres=# select 1 test;
test
------
1
(1 row)
-- 中断22秒再执行:
postgres=# \watch 22
Fri 11 Oct 2024 08:57:39 AM CST (every 22s)

test
------
1
(1 row)

FATAL: terminating connection due to idle-session timeout
server closed the connection unexpectedly
This probably means the server terminated abnormally
before or while processing the request.
The connection to the server was lost. Attempting reset: Succeeded.

我们会发现在20秒的时候,连接会被terminate。

这是PG14自带的功能。

上边设的是全局的。也可以设成当前session级别的,请看:

postgres=# set idle_session_timeout=10000;
SET
postgres=# select 1 test2;
test2
-------
1
(1 row)

postgres=# \watch 11
Fri 11 Oct 2024 09:01:50 AM CST (every 11s)

test2
-------
1
(1 row)

FATAL: terminating connection due to idle-session timeout
server closed the connection unexpectedly
This probably means the server terminated abnormally
before or while processing the request.
The connection to the server was lost. Attempting reset: Succeeded.

有点意思哈。附带个问题,如果不是psql这种命令行客户端,如果是jdbc应用,该怎么设,留个思考给读者。

当然,我们还可以使用下边的脚本,显式的杀掉你认为“超时”的空闲连接:

SELECT
pg_terminate_backend(pid)
FROM
pg_stat_activity
WHERE
state in ('idle', 'idle in transaction', 'idle in transaction (aborted)', 'disabled')
AND now() - query_start > '00:00:10';

或者复杂一点儿的:

WITH inactive_connections AS (
SELECT
pid,
rank() over (partition by client_addr order by backend_start ASC) as rank
FROM
pg_stat_activity
WHERE
pid <> pg_backend_pid( )
AND
application_name !~ '(?:psql)|(?:pgAdmin.+)'
AND
datname = current_database()
AND
usename = current_user
AND
state in ('idle', 'idle in transaction', 'idle in transaction (aborted)', 'disabled')
AND
current_timestamp - state_change > interval '60 minutes'
)
SELECT
pg_terminate_backend(pid)
FROM
inactive_connections
WHERE
rank > 1;

7、idle_in_transaction_session_timeout (+v9.6)

Sets the maximum allowed duration of any idling transaction

终止任何已经闲置超过这个参数所指定时间量的打开事务的会话。这使得该会话所持有的任何锁被释放,并且其所持有的连接槽可以被重用,它也允许只对这个事务可见的元组被清理。有关于此的详情请见routine-vacuuming。

如果指定值时没有单位,则以毫秒为单位。0值(默认值)禁用超时。

8、transaction_timeout (+v17)

Sets the maximum allowed duration of any transaction within a session (not a prepared transaction)

终止事务中任何超过指定时间的会话。该限制既适用于显式事务(以BEGIN开始),也适用于与单个语句对应的隐式启动的事务。如果该值没有指定单位,则以毫秒为单位。零值(默认值)禁用超时。

如果' transaction_timeout '小于或等于idle_in_transaction_session_timeout或statement_timeout,则忽略较长的超时。

不建议在postgresql.conf中设置' transaction_timeout ',因为它会影响所有会话

准备好的事务不受此超时的约束。

这意味着,我们可以在具体的连接会话当中设置此参数。在应用开发端应该比较有用。因为具体的应用对应的transaction_timeout可能不太相同。相对于idle_session_timeout , 这个参数功能更强大。

不过,我认为,它确实是一把双刃剑,需要针对不同性质的应用,作具体化的参数设计。尤其是用到数据库连接池的时候。一定要区分清楚,不然就有可能会造成错杀。


个人微信:_iihero
CSDN: iihero
墨天轮:https://www.modb.pro/u/16258 (Sean)

pgfans: iihero


往期导读: 
1. PostgreSQL中配置单双向SSL连接详解
2. 提升PSQL使用技巧:PostgreSQL中PSQL使用技巧汇集(1)
3. 提升PSQL使用技巧:PostgreSQL中PSQL使用技巧汇集(2)
4. PostgreSQL SQL的基础使用及技巧
5. PostgreSQL开发技术基础:过程与函数
6. PostgreSQL中vacuum 物理文件truncate发生的条件
7. PostgreSQL中表的年龄与Vacuum的实验探索:Vacuum有大用
8. PostgreSQL利用分区表来弥补AutoVacuum的不足
9. 也聊聊PostgreSQL中的空间膨胀与AutoVacuum
10. 正确理解SAP BTP中hyperscaler PG中的IOPS (AWS篇)
11. 由浅入深高可用(HA)之: HAProxy

数据库杂记
数据库技术专家,PostgreSQL ACE,SAP HANA,Sybase ASE/ASA,Oracle,MySQL,SQLite各类数据库, SAP BTP云计算技术, 以及陈式太极拳教学倾情分享。出版过三本技术图书,武术6段。
 最新文章