ORA-12170 根本原因是服务端 SQLNET.INBOUND_CONNECT_TIMEOUT(默认60秒且需显式配置)在认证阶段超时主动断连,而非网络不通;须修改数据库服务器端 sqlnet.ora 或 listener.ora 中对应监听器的 INBOUND_CONNECT_TIMEOUT 参数并 reload 监听器。
oracle 11g 远程连接频繁报 ora-12170: tns:connect timeout occurred 或服务端日志出现 warning: inbound connection timed out (ora-3136),根本原因不是网络不通,而是服务端在认证阶段主动切断了“慢连”——默认 sqlnet.inbound_connect_timeout 仅 60 秒,且该参数在 11g 中必须显式配置才生效。
ORA-12170 是服务端杀的,不是客户端等不及
很多用户以为改客户端 sqlnet.ora 就能解决,但实际起作用的是数据库服务器上的 sqlnet.ora(或 listener.ora 中对应 listener 的专用参数)。现象是:客户端卡住约 60 秒后直接失败,sqlplus 日志里看不到完整握手过程,而服务端 alert.log 和 sqlnet.log 会明确记录被中断的 IP 和时间戳。
-
SQLNET.INBOUND_CONNECT_TIMEOUT控制“从 TCP 连接建立完成 → 完成 Oracle 用户认证”的总窗口期 - 它不涉及 DNS 解析、TCP 握手、路由延迟——这些发生在该计时器启动之前
- 11g 默认值虽为 60 秒,但若该参数未在服务端
sqlnet.ora中显式声明,则可能退化为更短的实际超时(尤其在 RAC 或高负载下) - 不要设为 0,禁用会导致拒绝服务风险;建议设为
120或300
listener.ora 中的 INBOUND_CONNECT_TIMEOUT_LISTENER 优先级更高
当使用非默认监听器名(比如 LISTENER_SCAN 或自定义名 MYLISTENER)时,listener.ora 中的 INBOUND_CONNECT_TIMEOUT_<listener_name></listener_name> 会覆盖全局 SQLNET.INBOUND_CONNECT_TIMEOUT。这是 11gR2 起引入的细化控制机制。
- 例如监听器名为
MYLISTENER,则需在listener.ora中添加:INBOUND_CONNECT_TIMEOUT_MYLISTENER = 240 - 修改后必须执行
lsnrctl reload或lsnrctl stop && lsnrctl start,仅改文件不生效 - 可用
lsnrctl show inbound_connect_timeout验证当前值 - 官方建议:
INBOUND_CONNECT_TIMEOUT_<listener_name></listener_name>应小于全局SQLNET.INBOUND_CONNECT_TIMEOUT,否则可能引发不一致行为
DNS 解析慢会伪装成 ORA-12170,但它不在 SQLNET.INBOUND_CONNECT_TIMEOUT 管控范围内
如果客户端发起连接后卡在“解析主机名”阶段(比如 tnsnames.ora 写了 db.example.com 但 DNS 响应要 8 秒),服务端计时器还没启动,但用户看到的仍是 ORA-12170。这不是参数没设对,而是问题根本不在数据库侧。
- 先用
nslookup db.example.com或dig db.example.com测 DNS 延迟,>2s 就需干预 - 临时验证:把
tnsnames.ora中的主机名直接换成 IP,再试连接;秒连即证实是 DNS 问题 - 永久修复:在服务端和客户端的
sqlnet.ora中设置NAMES.DIRECTORY_PATH = (HOSTNAME, TNSNAMES, EZCONNECT),让系统优先走/etc/hosts或本地 resolver - 别在 11g 的
tnsnames.ora里加CONNECT_TIMEOUT=5——该参数 12cR1 才支持,11g 忽略甚至报错
Java 应用连不上?JDBC 不读 sqlnet.ora,得另配
Oracle JDBC Thin 驱动完全不加载客户端 sqlnet.ora,所以你在本地 $ORACLE_HOME/network/admin/sqlnet.ora 里调参,对 Spring Boot 或 WebLogic 里的数据源毫无影响。
- 必须通过 JDBC URL 显式传超时:
jdbc:oracle:thin:@(DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HOST=db)(PORT=1521))(CONNECT_DATA=(SERVICE_NAME=orcl))(CONNECT_TIMEOUT=30)) - 或者用
Properties设置:props.put("connectTimeout", "30000"); - 注意:JDBC 的
connectTimeout只控 TCP 连接建立,不控认证;认证阶段超时仍由服务端SQLNET.INBOUND_CONNECT_TIMEOUT决定 - 若用连接池(如 HikariCP),还需检查
connection-test-query和validation-timeout,避免池中“半死”连接在重用时触发二次超时
真正麻烦的从来不是改哪个参数,而是分不清超时发生在哪一层:DNS 解析、TCP 握手、服务端认证,还是应用层重试逻辑。先看服务端日志有没有 ORA-3136,再查客户端能否 telnet host 1521,最后才动 sqlnet.ora——顺序错了,调三天也白搭。


















