Connection request timed out 的真实含义是“拿不到连接”而非“连不上数据库”:因连接未释放导致连接池耗尽,新请求在Open()处阻塞至Connection Timeout后超时抛错,典型表现为v$session中大量INACTIVE连接、会话数卡在Max Pool Size值、重启后短暂恢复。
不是连接池太小,而是连接没释放完就满了——加到500也照样超时。
Connection request timed out 的真实含义
这个错误不是“连不上数据库”,而是“拿不到连接”。Oracle.ManagedDataAccess 默认开启连接池,Max Pool Size 默认 100。当所有连接被占用且未归还(比如 OracleDataReader 没关、using 块提前跳出、catch 里吞异常不释放),新请求就会卡在 Open() 调用上,等满 Connection Timeout 秒后抛出该异常。
常见现象包括:
- v$session 中大量
STATUS = 'INACTIVE'且LAST_CALL_ET > 1800(30分钟) - 应用 CPU/内存正常,但 Oracle 会话数稳定卡在
Max Pool Size值附近 - 重启 IIS 或应用池后瞬间恢复,几小时内复现
为什么只调大 Max Pool Size 是饮鸩止渴
单纯把 Max Pool Size=500 只是延缓问题爆发时间。只要代码中存在连接泄漏,池迟早再次耗尽。更糟的是,大池会掩盖泄漏点,让问题在压测后期或业务高峰才暴露,排查成本陡增。
真正该检查的三件事:
- 所有
OracleConnection是否都包裹在using块里,或显式调用了connection.Close() - 所有
OracleCommand.ExecuteReader()后是否对应reader.Close()(using最安全) - 是否在
catch块中捕获异常却不释放连接(例如只写log.Error(e)就返回)
连接字符串里真正影响高负载表现的参数
以下参数在 Oracle.ManagedDataAccess(12c/19c + .NET 6+)中生效,顺序不能错:
-
Pooling=true:必须显式写,某些旧部署环境默认为false -
Max Pool Size=100:设太高不解决泄漏,建议先保持默认,定位泄漏后再微调 -
Connection Timeout=15:控制“等连接”的最长时间(秒),设太小导致频繁报错,设太大让故障响应变慢 -
Validate Connection=true:每次从池取连接前做轻量 ping,能规避防火墙断连,但增加约 1–2ms 开销 -
Statement Cache Size=50:默认为 0(禁用),启用后显著减少硬解析,值超过 200 可能反而拖慢查找 -
Metadata Performance=Enabled:关键开关,跳过首次 DML 时查all_constraints等系统表的开销(高频租户分表场景必开)
最容易被忽略的底层超时链路
连接池超时只是表象,背后可能串着三层超时:
- 客户端 TCP 层:防火墙/负载均衡空闲超时(常为 60 秒),需配
sqlnet.ora的SQLNET.INBOUND_CONNECT_TIMEOUT=120 - ODP.NET 驱动层:
Connection Timeout控制“等连接”,socketTimeout(JDBC 有,.NET 需靠 OS 层)控制“连上后读响应” - 数据库服务端:
sqlnet.inbound_connect_timeout(服务端 sqlnet.ora)决定认证总时长,和客户端无关
如果看到 ORA-12170: TNS:Connect timeout occurred,大概率卡在 TCP 连接建立阶段,此时改连接字符串里的 Connection Timeout 完全无效。











