解决PostgreSql中一直有连接长时间处于idle in transaction的问题
在解决问题前,先来了解一下数据库连接的几种状态。
pg_stat_activity 是一张postgresql的系统视图,它的每一行都表示一个系统进程,显示与当前会话的活动进程的一些信息,比如当前会话的状态和查询等。它的state字段表示当前进程的状态,一共有六种:
Active(活动): 进程正在执行某个语句
Idle(空闲): 进程正在等待客户端的指令
idle in transaction(事务空闲):进程在处理事务的过程中,但当前没有执行任何语句
idle in transaction (aborted)(事务空闲-退出):除了事务中声明一个错误外,其余情况与idle in transaction相同
fastpath function call(快速通道函数调用): 后台正在执行某个快速通道函数
Disabled(禁用): 报告状态被禁用
实际测试一个连接常见状态:
开启另一个连接查询当前数据库的所有连接状态。
在创建的连接不执行任何语句的情况下,连接状态为:idle
以查询连接状态的会话为例,正在执行某个语句的连接状态为:active
尝试开启一个事务:
这时开启事务的连接状态变成了:idle in transaction
执行一些sql语句
查看连接状态,发现依然为idle in transaction
提交事务
状态重新变回idle
使用end,报警告,提示没有正在进行的事务
重新开启一个事务,执行一条插入语句。直接执行end;发现事务默认被提交
重新开启一个事务:
如果不做提交操作或者没有断开连接,那么连接状态就会一直处于idle in transaction。
Postgresql在9.6版本提供了idle_in_transaction_session_timeout 参数,用于释放一直处于idle in transaction状态下的连接。
尝试在postgresql.conf 文件中添加idle_in_transaction_session_timeout参数控制,参数单位为毫秒idle_in_transaction_session_timeout=30000
再次开启一个事务,执行一条查询语句,并查看该连接的状态
过了30秒后,pid为17197的连接被断开:
重新创建连接,不做任何操作(使连接处于空闲状态):
等待一段时间后,连接依然存在。
测试结果显示,增加了idle_in_transaction_session_timeout参数后,数据库会自动断开在事务空闲状态下的连接,而空闲状态下的连接不受影响。
尝试写一个一直在active状态下的sql(sql具体内容不要在意)
过了一段时间后,发现状态任然为 avtive
也就是说idle_in_transaction_session_timeout参数不会影响在active状态下的连接。