oracle监听器配置ipv6必须用方括号包裹地址(如[2001:db8::1]),否则解析失败;需设ip_address_listener=yes禁用ipv4映射,并同步更新local_listener参数。
listener.ora 里写 ipv6 地址必须加方括号
oracle 监听器不识别裸 ipv6 地址(比如 2001:db8::1),直接写会启动失败,报错类似 tns-12545: connect failed because target host or object does not exist 或更底层的 tns-12560: tns:protocol adapter error。根本原因是 oracle 内部解析地址时把冒号当成分隔符,没做 ipv6 字面量封装。
正确写法是把 IPv6 地址用方括号包起来,和 HTTP/URL 里的规则一致:
LISTENER =
(DESCRIPTION_LIST =
(DESCRIPTION =
(ADDRESS = (PROTOCOL = TCP)(HOST = [2001:db8::1])(PORT = 1521))
)
)- 方括号
[ ]是强制要求,缺一不可 -
HOST值支持 IPv6 字面量(如[::1])或 IPv6 域名(如[mydb-v6.example.com]),但域名需确保 DNS 返回 AAAA 记录且本地/etc/hosts或 resolver 能解析 - 不要混用 IPv4 和 IPv6 在同一个
ADDRESS块里——Oracle 不支持双栈单地址配置
监听器要真正绑定 IPv6,得关掉 IPv4 映射
默认情况下,Linux/Unix 上的 Oracle 监听器可能启用 IPv4-mapped IPv6 socket(即一个 socket 同时接受 IPv4 和 IPv6 连接),这看起来“能连”,但实际走的是 IPv4 协议栈,netstat -tlnp | grep 1521 会显示 tcp6 但监听在 :::,本质是通配模式,不是真正的 IPv6 绑定。
要让监听器只响应原生 IPv6 流量、并暴露真实 IPv6 端口状态,必须显式禁用映射:
ENABLE_GLOBAL_DYNAMIC_ENDPOINT_LISTENER=OFF DISABLE_ASYNCH_IO=ON # 部分版本配合使用,防异步 I/O 干扰 # 关键:强制使用纯 IPv6 socket IP_ADDRESS_<code>LISTENER</code>=<code>YES</code>
-
IP_ADDRESS_<code>LISTENER=YES是关键开关,它告诉 Oracle 使用AF_INET6socket 创建监听,而非默认的兼容模式 - 该参数需写在
listener.ora的顶层(不在 DESCRIPTION 块内),且修改后必须lsnrctl reload或lsnrctl stop && lsnrctl start - 验证是否生效:运行
lsnrctl status,看输出里Listening Endpoints Summary...是否明确列出(DESCRIPTION=(ADDRESS=(PROTOCOL=tcp)(HOST=[2001:db8::1])(PORT=1521))),而不是(HOST=*)(PORT=1521)
客户端连接 IPv6 监听器时,tnsnames.ora 也要套方括号
服务端配好了,客户端如果还用老写法,照样连不上。Oracle 客户端(sqlplus、JDBC thin、ODP.NET)对 IPv6 地址的解析逻辑和监听器一致——必须带方括号。
错误写法:(HOST = 2001:db8::1) → 解析失败,报 ORA-12170: TNS:Connect timeout occurred
正确写法:
MYDB6 =
(DESCRIPTION =
(ADDRESS = (PROTOCOL = TCP)(HOST = [2001:db8::1])(PORT = 1521))
(CONNECT_DATA = (SERVICE_NAME = orcl))
)- 方括号只包 IP,不包端口、不包协议,
[2001:db8::1]:1521是错的,Oracle 不认这种 URL 风格 - 如果用 JDBC,URL 格式为
jdbc:oracle:thin:@[2001:db8::1]:1521/orcl,同样不能省略方括号 - Windows 客户端要注意:某些旧版 Oracle Client(如 11.2.0.1)对 IPv6 支持不完整,建议至少用 12.1+ 版本
IPv6 网络通但连接被拒绝?检查防火墙和 Oracle 的 LOCAL_LISTENER
监听器日志($ORACLE_HOME/network/log/listener.log)里出现 TNS-12535: TNS:operation timed out 或 TNS-12547: TNS:lost contact,但 ping6 和 telnet [2001:db8::1] 1521 都通,问题大概率出在两处:
- 系统防火墙(
iptables/ip6tables或firewalld)没放开 IPv6 的 1521 端口,注意ip6tables是独立服务,和iptables无关 - 数据库实例里
LOCAL_LISTENER参数没同步更新,导致实例注册到监听器时仍用 IPv4 地址,造成“监听器知道有这个服务,但连过去找不到实例”。查一下:SELECT value FROM v$parameter WHERE name = 'local_listener';,应设为(ADDRESS=(PROTOCOL=TCP)(HOST=[2001:db8::1])(PORT=1521)),然后执行ALTER SYSTEM REGISTER; - 部分云环境(如 OCI、AWS)的网络 ACL 或安全组默认禁用 IPv6 流量,需手动添加入站规则
IPv6 的地址格式、socket 行为、工具链支持都比 IPv4 更敏感,少一个方括号、漏一条防火墙规则、或者忘了刷新 LOCAL_LISTENER,都会让整个链路静默失败。别依赖“看起来能 ping 通”就认为配置完成。










