ora-00060与超时并发多因防火墙拦截导致网络不通,非真实死锁;应优先验证链路可达性(telnet、lsof查lgwr连接)、mtu(ping -s 8972)、selinux状态,并确认standby_file_management=auto、log_archive_dest_state_2=enable及mrp已启动。

ORA-00060 和超时(如 ORA-12170、ORA-12537、LGWR/ARCH timeout)在 Data Guard 环境中同时出现,基本不是真死锁,而是网络层阻断引发的会话堆积与日志传输卡死。Oracle 本身不会因防火墙拦截产生跨实例死锁,但防火墙若只放行部分端口或做连接限制,会导致 RFS 进程收不到日志、MRP 等待日志超时、LNS/LGWR 持续重试,最终表现为大量会话 hang 在 enq: TX - row lock contention 或 gc cr request 上——这是表象,根因是网络不通。
确认是不是防火墙在拦日志流
别急着查 v$lock 或 kill session,先验证底层链路是否真实可达:
- 主库上用
tnsping standby_db只能测监听通,不能代表日志传输通道通;必须用sqlplus / as sysdba连备库并执行SELECT 1 FROM DUAL@standby_db(需配置数据库链接)或直接sqlplus sys@standby_db as sysdba——失败则大概率是网络问题 - 在主库服务器执行:
telnet standby_ip 1521测监听端口,再执行:telnet standby_ip 22(如果用了 SSH 隧道)或实际 DG 通信端口(如自定义的 1522) - 重点检查:DG 默认走的是 Oracle Net(TNS),但部分环境会强制日志传输走专用网段或非标准端口;用
lsof -i :1521 | grep -i lgwr查主库 LGWR 是否已建立到备库 IP 的 TCP 连接;若无 ESTABLISHED 状态连接,90% 是防火墙或路由拦截 - 备库上查 RFS 进程是否启动:
ps -ef | grep rfs;若没有,或只有rfs但无对应线程号(如rfs_1、rfs_2),说明主库根本没连上来
防火墙常见误配点(Oracle 19c DG 特有)
Oracle DG 不只是“连得上就行”,它对连接稳定性、分片、MTU、双向通信都有隐性要求:
-
ping -s 8972 standby_ip必须成功——这是 Oracle 检测 MTU 的标准包大小;若丢包或超时,说明中间防火墙/交换机做了 ICMP 限速或禁止大包,导致日志传输分片失败,RFS 收到不完整块后静默丢弃,表现就是 transport lag 持续上涨、MRP 卡在WAIT_FOR_LOG - 防火墙若启用了“连接跟踪”(stateful inspection),可能对长时间空闲的 LGWR→RFS 连接做超时清理(默认常为 30–60 分钟);结果是主库认为连接还在发日志,备库 RFS 实际已断开,后续日志全丢,主库报
LGWR network timeout,备库V$MANAGED_STANDBY中 RFS 状态为IDLE或CONNECTED但无接收记录 - RAC 环境下,防火墙必须放行所有节点 IP 到备库 SCAN VIP 的 1521 端口,且不能只放行一个节点;否则 THREAD 2 的日志永远传不过去,
V$DATAGUARD_STATS中transport lag持续增长,但V$ARCHIVE_DEST_STATUS显示STATUS = VALID——极具迷惑性 - 若用
LOG_ARCHIVE_DEST_2配置了ASYNC,防火墙还必须允许主库向备库反向发起连接(比如 broker 心跳、DG Broker 的 DGMGRL 连接),否则DGMGRL SHOW CONFIGURATION会报ORA-12545或状态为WARNING
怎么快速验证和绕过防火墙干扰
临时关闭防火墙不是目的,而是为了定位;生产环境要改策略,不是关服务:
- Oracle Linux 7.8+ 上临时停防火墙:
systemctl stop firewalld,再立刻查V$ARCHIVE_DEST_STATUS和V$MANAGED_STANDBY;若 RFS 状态秒变RECEIVING、transport lag 开始下降,就坐实是防火墙问题 - 不要只加一条
firewall-cmd --add-port=1521/tcp;DG 日志流实际使用的是动态分配的高阶端口(尤其 RFS 接收时),正确做法是按 Oracle 官方建议,开放整个 Oracle Net 端口范围:firewall-cmd --add-port=1521-1530/tcp,或更稳妥地基于服务名:firewall-cmd --add-service=oracle(需提前定义 service 文件) - 若无法改防火墙策略,可在主备之间加一层 SSH 隧道(仅限测试):
ssh -L 1522:standby-scan:1521 oracle@standby_node1,然后把LOG_ARCHIVE_DEST_2的SERVICE指向localhost:1522;注意这会引入额外延迟,不可用于生产 - 最易被忽略的一点:SELinux 若为
enforcing,即使防火墙放行,也可能拦截 Oracle 进程的网络 bind/connect 行为;临时禁用:setenforce 0,永久修改需改/etc/selinux/config中SELINUX=disabled
防火墙修复后仍卡在 WAIT_FOR_LOG?检查三个硬性配置
网络通了不代表 DG 就自动跑起来;很多 DBA 以为“通了就能同步”,结果 MRP 一直挂起,根源是参数没跟上:
-
standby_file_management必须为AUTO:ALTER SYSTEM SET standby_file_management=AUTO SCOPE=BOTH;;否则主库新增数据文件,备库无法自动创建,MRP 会卡住并报ORA-01111 -
log_archive_dest_state_2必须为ENABLE,且不能是DEFER;查V$ARCHIVE_DEST_STATUS中STATUS字段,若为DEFERRED,说明之前网络中断触发了自动 defer,需手动ALTER SYSTEM SET log_archive_dest_state_2=ENABLE; - 备库必须已启动 MRP:
ALTER DATABASE RECOVER MANAGED STANDBY DATABASE USING CURRENT LOGFILE DISCONNECT FROM SESSION;;只启库不启 MRP,日志来了也白来
真正难的不是发现防火墙拦了,而是它拦得“不彻底”:部分连接通、部分超时、偶尔丢包——这种场景下,ORA-00060 日志里看到的“阻塞会话”,往往只是下游等待上游日志的连锁反应,源头早被防火墙无声掐断。盯住 V$MANAGED_STANDBY 和 tcpdump -i any port 1521,比翻 alert.log 有效得多。











