EXPIRE_TIME是服务端死连接探测参数,单位分钟,仅对Oracle Net连接有效;设为0表示禁用,非立即检测,且不主动断开健康连接。
expire_time 不是“连接池断开”的原因,而是你误判了故障根源——它只清理已断开的连接,不会主动断开健康连接。
EXPIRE_TIME 本质是探测器,不是断连开关
EXPIRE_TIME 在 sqlnet.ora 中配置,单位是分钟(注意:不是秒),作用是让 Oracle 数据库服务端定期向客户端发一个空 TCP probe。它只对已建立、但可能已异常中断(如客户端崩溃、防火墙静默回收)的空闲连接起效。如果 probe 没收到响应,数据库才清理对应进程和会话。
- 设成
EXPIRE_TIME = 1不会让连接“更快断开”,只会每分钟发一次探测——在高并发下显著增加内核系统调用和网络包,反而拖慢监听器响应 - 它对 JDBC Thin 驱动完全无效(Thin 不走 Oracle Net 协议栈),只影响 OCI、JDBC Thick 或 SQL*Plus 等走 Oracle Net 的连接
- 值为 0 表示禁用,不是“立即检测”;不配或配错路径,等于没配
真正导致“频繁断开”的常见组合
连接池里出现大量 INACTIVE 状态却突然失效,往往不是 EXPIRE_TIME 太大,而是它和其它机制打架:
-
IDLE_TIME在用户 profile 中被设为 30(单位:分钟):数据库会在空闲 30 分钟后直接KILL SESSION,不管网络是否通畅 - 应用连接池的
max-lifetime设为 60 分钟,但数据库侧EXPIRE_TIME = 10+ 防火墙空闲超时 15 分钟 → 探测节奏和设备策略不匹配,probe 总是晚于断连发生 - 客户端
sqlnet.ora里误配了SQLNET.RECV_TIMEOUT = 5:这不是服务端参数,而是客户端收包空闲超时,会导致查询中途被硬中断
怎么配才不踩坑
先确认问题类型:抓一次 SQLRecoverableException: IO Error: Connection reset 发生前后的数据库审计日志,看 v$session.last_call_et 是否接近某个固定分钟数(比如总在 15 分或 30 分整点附近断),再查 DBA_PROFILES 和防火墙策略。
- 若断连集中在固定空闲时长(如 30 分钟),优先查
IDLE_TIME:SELECT LIMIT FROM DBA_PROFILES p JOIN DBA_USERS u ON p.PROFILE = u.PROFILE WHERE u.USERNAME = 'YOUR_USER' AND p.RESOURCE_NAME = 'IDLE_TIME' - 若断连时间不固定但总伴随网络抖动,再调
EXPIRE_TIME:设为防火墙空闲超时的 1/3~1/2,例如防火墙是 30 分钟,则SQLNET.EXPIRE_TIME = 10 - 必须同步改应用层:HikariCP 的
max-lifetime建议设为EXPIRE_TIME × 2.5,Druid 的time-between-eviction-runs-millis要小于EXPIRE_TIME × 60000
验证配置是否真生效
改完 $ORACLE_HOME/network/admin/sqlnet.ora 后,别重启数据库——新连接才会加载。验证分三步:
- 连上后执行:
SELECT sys_context('USERENV', 'NETWORK_PROTOCOL') FROM DUAL,确保返回tcp - 查当前会话空闲时间:
SELECT sid, last_call_et, status FROM v$session WHERE username = 'YOUR_USER',观察last_call_et是否随时间递增,且在接近EXPIRE_TIME × 60秒时突变为 0 并消失 - 用
tnsping加非法项测试文件是否被读取,比如加一行INVALID.PARAM=1,再运行tnsping—— 若报错不是TNS-03505,说明文件已加载
复杂点在于:同一套参数在 RAC 所有节点必须一致;而 JDBC Thin 用户根本不受影响,得换用 oracle.net.CONNECT_TIMEOUT 和连接池心跳协同防御。


















