Connection request timed out 是连接池耗尽而非网络故障,表现为 NumberOfFreeConnections=0 和大量 INACTIVE 会话;应按错误码精准调用 ClearPool 或 ClearAllPools;Validate Connection=true 无效且有害,应设为 false 并用 Connection Lifetime=600 配合轻量心跳。

Connection request timed out 是连接池满了,不是连不上
看到 Connection request timed out 别急着查网络或监听器——tnsping 通、sqlplus 能登录,就说明数据库端没问题。真实原因是:连接池里所有 OracleConnection 都被占着没归还,新请求在 Open() 处排队等超时。典型表现是 Windows 性能计数器里 NumberOfFreeConnections 长期为 0,v$session 中大量 STATUS = 'INACTIVE' 且 LAST_CALL_ET > 1800。
ClearPool 和 ClearAllPools 的触发时机必须精准
ODP.NET 不会自动清理失效连接,得靠代码主动干预。但不能一出错就无脑调 OracleConnection.ClearAllPools()——它会清空所有池,引发瞬时建连风暴,压垮数据库。正确做法是按错误码分类处理:
-
ORA-03113、ORA-03135、ORA-01041:说明连接已断,用OracleConnection.ClearPool(conn)清对应池(conn必须是非 null 且已打开过的实例) -
ORA-00028、ORA-02396、ORA-12535:会话被 kill 或空闲超时,同样走ClearPool - 其他未覆盖的异常,或
conn == null场景,才退化到ClearAllPools()
注意:这些清理操作必须放在 catch 块里,且确保在 Dispose() 或 Close() 之后执行,否则可能因连接状态不一致导致清理失败。
Validate Connection=true 在 Oracle 场景下基本不可用
设 Validate Connection=true 看似能提前筛掉坏连接,但在 Oracle 实际环境里几乎无效甚至有害:
- 托管 ODP(
Oracle.ManagedDataAccess)多个版本中该参数实际不生效(2020 年验证确认) - 即使生效,每次取连接都执行
SELECT 1 FROM DUAL,在网络抖动或防火墙空闲断连时反而引发验证超时,把本可用的连接丢弃 - 验证串行化竞争,在低配置池(如
Min Pool Size=1)下放大延迟,形成雪崩
生产环境一律设 Validate Connection=false,靠 Connection Lifetime=600(10 分钟)强制刷新连接更可靠。
Connection Lifetime=60 是陷阱,0 也不等于永生
Connection Lifetime=60 是常见误配:它让每个连接最多活 60 秒,频繁重建连接,性能反降。而 Connection Lifetime=0(默认)也不是“永不销毁”,只是不主动到期——但数据库重启、RAC VIP 切换、TNS 探活失效后,池里仍会堆积陈旧连接。
真正平衡点是 Connection Lifetime=600(10 分钟),配合应用层轻量心跳(比如 Timer 每 30 秒新建一个非池连接做 Open()/Close() 探针),既能避免假活连接滞留,又不增加主池负担。
最易被忽略的是:连接字符串里一个空格、大小写差异、分号位置不同,都会分裂出独立连接池——监控时看到多个池各卡在 Max Pool Size 上限,却以为是单个池耗尽。


















