Connection request timed out 的根本原因是连接池耗尽,90% 情况因 OracleConnection 未 Dispose/Close 导致连接泄漏,且 ODP.NET 不依赖 GC 而只认显式释放;连接字符串字符级差异、Connection Lifetime 非零、Max Pool Size 超数据库 processes 限制等均加剧此问题。

Connection request timed out 不是连不上库,是池子里没连接可拿了——90% 的情况,连接根本没归还。
OracleConnection 没 Dispose 就等于没还连接
ODP.NET 不靠 GC 回收连接,只认 Dispose() 或 Close()。漏掉这一步,连接就卡在池里不动,状态变成 INACTIVE,但池子不认它“空闲”。
-
using (var conn = new OracleConnection(cs)) { if (x) return; }—— 提前return,conn不会Dispose -
try { cmd.ExecuteNonQuery(); } catch { log.Error(); return; }—— 异常路径没释放 -
OracleDataReader用完没调reader.Close()或没包进using - 把
OracleConnection存成类字段或静态变量,长期持有
连接字符串差一个空格,池就分裂
ODP.NET 按连接字符串**逐字符比对**决定是否复用。大小写、空格、分号位置、换行符不同,都会新建独立池。
-
Max Pool Size=100✅;Max Pool Size = 100❌(等号前后空格导致参数被忽略) -
Data Source=ORCL和Data Source=orcl被视为两个池 - 拼接字符串时用
$"Data Source={host}",host带空格或大小写不一致,池就碎了
Connection Lifetime=60 是性能杀手
设成非零值,会让从池取出的连接一旦存活超时就被标记“过期”,归还时直接关闭,不进池——相当于主动废掉复用能力。
- 生产环境推荐设为
Connection Lifetime=0 -
Connection Lifetime=60看似防老化,实则让连接频繁重建,加剧池压力 - 如果真要防断连,优先调
Validate Connection=false(默认就是 false),别靠 Lifetime
Max Pool Size 设太高反而触发 ORA-12519
池大小不是越大越好。Oracle 数据库端有 processes 限制,超出就会拒绝新连接。
- 先查数据库上限:
SELECT value FROM v$parameter WHERE name = 'processes'; -
Max Pool Size建议 ≤ 该值的 70% - 同步检查
Min Pool Size是否设得过高(如 50),冷启动就占满资源,却无实际收益 -
NumberOfFreeConnections长期为 0 +NumberOfActiveConnections卡在Max Pool Size附近,就是铁证
真正难排查的,是那些“看着像网络问题”的假象:tnsping 通、sqlplus 能连、v$session 会话数远低于池活跃数——这时候,别调 Connect Timeout,先翻代码里 every single OracleConnection 的生命周期。


















