Aekor

Aekor
专注于用户阅读体验的响应式博客主题
  1. 首页
  2. Oracle 数据库
  3. 正文

Oracle 连接层:TNSNAMES 高可用配置与 IP 黑白名单

2026-03-20 16267点热度 0人点赞 0条评论

客户端连不上、切换不自动、某台机器被挡在外面,这三类问题经常同时出现在“连接层”。前者归 TNSNAMES 管,后者归 sqlnet.ora 管,两边都不需要改数据库参数。本文上半部分讲怎么让客户端在 RAC 里自动分流和故障转移,下半部分讲怎么用监听层做 IP 白名单和黑名单,并给出单机与 RAC 的差异。

所有示例基于 Oracle 19c,单机监听端口示例为 1526,RAC 使用 SCAN。主机名、IP、服务名都要按实际环境替换。

一、TNSNAMES:让连接自动选节点

一个最朴素的 TNS 条目只写了地址和服务名,能连上,但不会分流,也不会在主节点故障时自动重连。加上下面几个参数后才有高可用行为:

  • LOAD_BALANCE = ON:在地址列表中随机挑选,分摊新连接。
  • FAILOVER = ON:某个地址连不上时尝试下一个。
  • FAILOVER_MODE:连接建立后,实例故障时会话级的重试与重建。

要区分两件事:FAILOVER 管的是“连接建立阶段换地址”,FAILOVER_MODE 管的是“会话已经建立后,实例挂了怎么办”。前者对所有环境有效,后者只有 RAC(或配置了 Data Guard 的 TYPE=SESSION 场景)才有意义。

1. 按 VIP 配置多节点

TEST =
  (DESCRIPTION =
    (LOAD_BALANCE = ON)
    (FAILOVER = ON)
    (ADDRESS_LIST =
      (ADDRESS = (PROTOCOL = TCP)(HOST = ora19c01)(PORT = 1521))
      (ADDRESS = (PROTOCOL = TCP)(HOST = ora19c02)(PORT = 1521))
    )
    (CONNECT_DATA =
      (SERVER = DEDICATED)
      (SERVICE_NAME = test)
      (FAILOVER_MODE =
        (TYPE = SELECT)
        (METHOD = BASIC)
        (RETRIES = 180)
        (DELAY = 5)
      )
    )
  )

节点更多时继续往 ADDRESS_LIST 里加 ADDRESS 即可。LOAD_BALANCE 只在 ADDRESS_LIST 内生效,写在 DESCRIPTION 下但没有地址列表时不起作用。

FAILOVER_MODE 的参数含义:

  • TYPE = SELECT:故障时把未提交的 SELECT 重新执行。SESSION 只重建会话,不重放语句;NONE 关闭。
  • METHOD = BASIC:连接失败时立即尝试下一个地址。PRECONNECT 会预先建立备用连接,切换更快但常驻占用资源。
  • RETRIES = 180、DELAY = 5:每 5 秒重试一次,最多 180 次,合计 15 分钟。

TYPE = SELECT 只对查询友好。有未提交事务的会话切换过去会失败,这是设计如此,不要指望它接管写事务。

2. 用 SCAN 的三种写法

RAC 环境下更推荐连 SCAN,由 SCAN 监听把连接分到各节点,客户端不需要知道节点名单。

多个 SCAN IP,显式地址列表:

TEST =
  (DESCRIPTION =
    (ADDRESS_LIST =
      (ADDRESS = (PROTOCOL = TCP)(HOST = ora19c-scan-ip1)(PORT = 1521))
      (ADDRESS = (PROTOCOL = TCP)(HOST = ora19c-scan-ip2)(PORT = 1521))
      (ADDRESS = (PROTOCOL = TCP)(HOST = ora19c-scan-ip3)(PORT = 1521))
    )
    (CONNECT_DATA =
      (SERVER = DEDICATED)
      (SERVICE_NAME = test)
      (FAILOVER_MODE =
        (TYPE = SELECT)
        (METHOD = BASIC)
        (RETRIES = 180)
        (DELAY = 5)
      )
    )
  )

单个 SCAN 主机名,交给 DNS 轮询:

TEST =
  (DESCRIPTION =
    (ADDRESS = (PROTOCOL = TCP)(HOST = ora19c-scan)(PORT = 1521))
    (CONNECT_DATA =
      (SERVER = DEDICATED)
      (SERVICE_NAME = test)
      (FAILOVER_MODE =
        (TYPE = SELECT)
        (METHOD = BASIC)
        (RETRIES = 180)
        (DELAY = 5)
      )
    )
  )

单个 SCAN IP:

TEST =
  (DESCRIPTION =
    (ADDRESS = (PROTOCOL = TCP)(HOST = ora19c-scan-ip1)(PORT = 1521))
    (CONNECT_DATA =
      (SERVER = DEDICATED)
      (SERVICE_NAME = test)
      (FAILOVER_MODE =
        (TYPE = SELECT)
        (METHOD = BASIC)
        (RETRIES = 180)
        (DELAY = 5)
      )
    )
  )

只有多个 SCAN 地址时才需要 LOAD_BALANCE。单个 SCAN 主机名时,DNS 返回多个 A 记录,客户端默认取第一个,开 LOAD_BALANCE 反而可能因为地址顺序问题带来额外延迟,按实际测试结果决定。

3. 负载均衡不是“智能调度”

原文里有一张“按业务场景选算法”的表,把 OLTP 对应会话计数、OLAP 对应响应时间。需要说清楚:客户端 LOAD_BALANCE 做的是连接建立时的随机选择,不是按负载动态调度,也不会在运行中迁移会话。真正的运行时负载均衡要靠服务端的连接池、Resource Manager 或中间件。

如果业务是短连接为主,客户端随机分流效果明显;如果是长连接,连接一旦建立就不再变化,节点间会逐渐倾斜。这种情况用 SCAN 加服务端配置更合适。

二、sqlnet.ora:在监听层做 IP 访问控制

比起在数据库里建触发器,sqlnet.ora 的限制发生在连接建立阶段,成本低得多,也不会因为触发器失效而被绕过。三个参数:

tcp.validnode_checking = yes
tcp.invited_nodes = (ip1, ip2)     # 白名单
tcp.excluded_nodes = (ip1, ip2)    # 黑名单

规则:

  • 开 invited_nodes 时,不在列表里的 IP 和主机名全部拒绝。
  • 开 excluded_nodes 时,只拒绝列表中的地址,其余放行。
  • 两者互斥。同时存在时 invited_nodes 优先。
  • 必须把本机地址和集群其他节点加进白名单,否则监听可能起不来。
  • 只对 TCP 生效,IPC 连接不受影响。
  • 改完执行 lsnrctl reload 或重启监听即可,不需要重启数据库。

白名单模式风险更高:漏掉一个应用服务器就是一次故障。上线前先把所有来源 IP 列全,或者先用黑名单挡掉明确的恶意地址。

1. 黑名单:拒绝某台机器

在数据库主机 192.168.61.137 上编辑 $ORACLE_HOME/network/admin/sqlnet.ora:

# sqlnet.ora Network Configuration File: /oracle/app/19.3.0/db_1/network/admin/sqlnet.ora
# Generated by Oracle configuration tools.

NAMES.DIRECTORY_PATH= (TNSNAMES, ONAMES, HOSTNAME)

SQLNET.ALLOWED_LOGON_VERSION_SERVER=8
SQLNET.ALLOWED_LOGON_VERSION_CLIENT=8

tcp.validnode_checking = yes
tcp.excluded_nodes = (192.168.61.138)

重启监听:

[oracle@ora19c-single admin]$ lsnrctl stop
[oracle@ora19c-single admin]$ lsnrctl start
[oracle@ora19c-single admin]$ lsnrctl status

此时如果监听原本没在跑,stop 会报 TNS-12541: TNS:no listener,属于正常现象,直接 start 即可。

在 192.168.61.138 上验证:

[oracle@ora19c-gt admin]$ tnsping single

TNS Ping Utility for Linux: Version 19.0.0.0.0 - Production on 03-APR-2026 19:38:43
...
Attempting to contact (DESCRIPTION = (ADDRESS = (PROTOCOL = TCP)(HOST = 192.168.61.137)(PORT = 1526)) (CONNECT_DATA = (SERVER = DEDICATED) (SERVICE_NAME = single)))
TNS-12547: TNS:lost contact
[oracle@ora19c-gt admin]$ sqlplus 'system/[email protected]:1526/single'

ERROR:
ORA-12547: TNS:lost contact

注意报错是 TNS-12547 而不是“拒绝连接”。这是监听接受了 TCP 握手后在协议层断开,容易被误判成网络问题。看到 12547 又确认网络通,先查 sqlnet.ora。

2. 白名单:只允许指定机器

把 excluded_nodes 注释掉,换成 invited_nodes,本机 127.0.0.1 和自身 IP 必须写进去:

tcp.validnode_checking = yes
#tcp.excluded_nodes = (192.168.61.138)
tcp.invited_nodes = (127.0.0.1, 192.168.61.137, 192.168.61.138)

同样重启监听后,从 192.168.61.138 连接应当成功:

[oracle@ora19c-gt ~]$ sqlplus 'system/[email protected]:1526/single'

Connected to:
Oracle Database 19c Enterprise Edition Release 19.0.0.0.0 - Production
Version 19.3.0.0.0

如果本机 sqlplus / as sysdba 用的是 IPC 或 BEQ,不受影响;但通过 TCP 连本机监听时,127.0.0.1 和主机名解析出的 IP 都要在列表里。主机名和 IP 混用时,Oracle 会做反向解析,解析结果不一致也会被拒——这是白名单最常见的坑,建议统一写 IP。

3. 顺手关掉本地认证

如果希望禁止 sqlplus / as sysdba 这类本地 OS 认证登录,在 sqlnet.ora 里加一行:

sqlnet.authentication_services=(none)

这一条影响面很大:所有依赖 OS 认证的脚本、RMAN 备份、crontab 都会失效。改之前先确认没有这类任务,或者保留密码文件认证作为替代。

4. RAC 环境的差异

配置内容与单机一致,差别在生效范围:每个节点都有自己的 sqlnet.ora,要逐个修改;监听要用 srvctl 管理,SCAN 监听也要重启。

srvctl stop listener -n ora19c-rac01
srvctl start listener -n ora19c-rac01
srvctl status listener -n ora19c-rac01

srvctl stop listener -n ora19c-rac02
srvctl start listener -n ora19c-rac02
srvctl status listener -n ora19c-rac02

srvctl stop scan_listener
srvctl start scan_listener
lsnrctl status LISTENER_SCAN1

只改一个节点会出现“连得上、连不上全看 SCAN 把你分到哪”的随机故障。白名单里还要包含所有节点 VIP、SCAN VIP 以及客户端网段,否则节点间的心跳或服务注册可能被自己挡住。

三、检查清单

  1. TNS 条目先用 tnsping 确认解析到预期地址,再看 sqlplus 是否成功。
  2. RAC 场景确认 SERVICE_NAME 是服务名而不是实例名,srvctl status service 看服务是否在目标节点运行。
  3. 出现 ORA-12547/TNS-12547,先排除网络,再查 sqlnet.ora 的 excluded_nodes。
  4. 开白名单前,把本机、集群节点、SCAN VIP、应用服务器 IP 全部列全。
  5. 改完用 lsnrctl reload 生效,RAC 用 srvctl 逐节点重启并检查 lsnrctl status。

原文首发于微信公众号「止水研习社」。

本作品采用 知识共享署名 4.0 国际许可协议 进行许可
标签: Oracle RAC TNSNAMES 访问控制
最后更新:2026-10-17

Aekor

这个人很懒,什么都没留下

点赞
< 上一篇
下一篇 >

文章评论

razz evil exclaim smile redface biggrin eek confused idea lol mad twisted rolleyes wink cool arrow neutral cry mrgreen drooling persevering
取消回复

使用AI教程

  • API报错解决方案
  • API 基础知识
  • API Key 获取
  • 最新接入教程

分类

  • Blog
  • Oracle 数据库
  • TradingAgents-CN
  • 使用教程
  • 数据库

COPYRIGHT © 2026 Aekor. ALL RIGHTS RESERVED.

Theme Kratos Made By Seaton Jiang