Oracle Connection Manager(CMAN)本质是代理网关,非连接池,不缓存或复用JDBC连接,仅做TCP层转发与策略控制;其核心价值在于集中限流、IP白名单及RAC流量染色,不解决ORA-12519/03113等数据库层问题,也不替代HikariCP等应用连接池。

Oracle Connection Manager 不是连接池,别把它当 HikariCP 用
CMAN(Connection Manager)本质是代理网关,不是连接池实现。它不缓存、不复用、不管理 JDBC Connection 对象,只做 TCP 层的连接转发和策略控制。很多团队误以为配了 CMAN 就能替代 UCP 或 HikariCP,结果应用层连接池照样泄漏、超时、卡死——因为 CMAN 完全不感知事务生命周期或连接空闲状态。
它的核心价值在三个地方:集中式连接限流、客户端 IP 白名单控制、RAC 节点流量染色(比如把来自特定微服务的请求固定打到 node2)。如果你的需求是“让连接池更稳”,CMAN 是配角,不是主角。
- CMAN 不处理
ORA-12519(会话数满):它转发请求,但不判断数据库processes是否已满 - CMAN 不缓解
ORA-03113(连接静默断开):它不主动探测后端连接有效性,也不重连 - CMAN 的
max_connections是它自己进程级的并发上限,和 Oracle 数据库的processes参数无直接换算关系
CMAN + RAC 的正确协作姿势:必须配合 SCAN 和服务名路由
CMAN 本身不理解 RAC 的服务注册机制,所以它不能自动发现新节点或感知故障转移。你必须显式告诉它怎么转发——靠配置里的 ADDRESS_LIST 和 SERVICE_NAME 映射。常见错误是把 CMAN 配成直连单实例,比如写 (HOST=rac-node1),这会让所有流量钉死在一个节点上,彻底废掉 RAC 的负载均衡能力。
正确做法是让 CMAN 指向 SCAN 地址,并确保其监听器注册了完整服务:
- CMAN 的
connection_policy中的address_list必须指向rac-scan(而非具体节点 IP),且 DNS 必须返回全部 3 个 SCAN VIP -
service_name配置项必须填数据库服务名(如orclpdb),不能填实例名(如rac1) - 检查 CMAN 日志是否出现
TNS-12514:大概率是 SCAN listener 没注册该服务,而不是 CMAN 配错了
CMAN 的 connection_pooling 参数只影响代理层,不影响应用连接池行为
CMAN 支持 connection_pooling(通过 cman.ora 中的 pool_size 和 min_pool_size),但这只是它自己维护的“到后端数据库的 TCP 连接池”,和 Java 应用里的 HikariCP 或 UCP 完全隔离。开启它不会减少应用层创建连接的次数,也不会降低数据库 processes 消耗。
这个参数的真实作用是:减少 CMAN 进程频繁建连/断连 Oracle 监听器的开销。但它有副作用:
- 开启后,CMAN 可能复用一条 TCP 连接到多个应用会话,导致
SQL_TRACE或V$SESSION中看到“一个连接混着多个用户事务”,排查问题变难 - 如果后端 RAC 节点重启,CMAN 的连接池可能持有已失效的 socket,需依赖
inactivity_timeout触发清理(默认 30 分钟,太长) - 建议仅在 CMAN 与数据库之间网络延迟高(>20ms)、且应用连接非常短临时(connection_pooling=off
真正要调的还是应用层连接池:UCP 或 HikariCP 才管 RAC 故障转移
CMAN 再怎么配,都无法让 UCP 自动感知节点故障并触发 FCF(Fast Connection Failover)。那个能力取决于 JDBC URL 里有没有 FAILOVER_MODE、驱动版本是否 ≥ 21c、ONS 配置是否正确。CMAN 只是透明地把带 FAILOVER 的连接请求原样转发过去。
所以最终生效链路是:应用 → CMAN → SCAN listener → RAC 实例。其中只有“应用 → CMAN”和“SCAN listener → RAC 实例”这两段支持故障转移,中间 CMAN 本身是个单点(除非你部署 CMAN 集群)。
- Java 用 UCP:必须设
setONSConfiguration("nodes=rac-node1:6200,rac-node2:6200"),CMAN 不参与 ONS 订阅 - Spring Boot 用 HikariCP:JDBC URL 里仍要保留
(FAILOVER_MODE=(TYPE=SESSION)(METHOD=BASIC)),CMAN 不解析也不改写这部分 - CMAN 的日志里如果高频出现
ERROR: connection refused,优先查 SCAN listener 状态,而不是调 CMAN 的max_connections
CMAN 的复杂性藏在它和 SCAN、ONS、RAC service 三者的时序耦合里——比如 SCAN VIP 切换后,CMAN 不会自动刷新 DNS 缓存,得手动 reload 或等 TTL 过期。这种细节不压测根本暴露不出来。


















