【问题解决】在docker中安装oracle19c数据库可以通过docker虚拟地址和本机ip连接但是无法通过本地回环localhost连接,回环连接卡住60秒后断开。

问题特征:
使用dbeaver连接时卡住60秒报错为“无法从套接字获取更多数据”
使用ojdbc8.jar这个驱动连接时在一个叫logon的函数中卡住60秒,然后报错连接重置
使用ojdbc17.jar连接时也是在logon函数卡住60秒然后报错连接被对等方关闭。
在docker的日志中可以看到如下日志

2025-09-08T16:49:44.328041149Z ***********************************************************************
2025-09-08T16:49:44.328057590Z 
2025-09-08T16:49:44.328074992Z Fatal NI connect error 12537, connecting to:
2025-09-08T16:49:44.328081334Z  (ADDRESS=(PROTOCOL=tcp)(HOST=172.17.0.1)(PORT=34410))
2025-09-08T16:49:44.328087375Z 
2025-09-08T16:49:44.328093486Z   VERSION INFORMATION:
2025-09-08T16:49:44.328099367Z 	TNS for Linux: Version 19.0.0.0.0 - Production
2025-09-08T16:49:44.328105809Z 	Oracle Bequeath NT Protocol Adapter for Linux: Version 19.0.0.0.0 - Production
2025-09-08T16:49:44.328111970Z 	TCP/IP NT Protocol Adapter for Linux: Version 19.0.0.0.0 - Production
2025-09-08T16:49:44.328118292Z   Version 19.3.0.0.0
2025-09-08T16:49:44.328124323Z   Time: 08-SEP-2025 16:49:43
2025-09-08T16:49:44.328130344Z   Tracing not turned on.
2025-09-08T16:49:44.328136205Z   Tns error struct:
2025-09-08T16:49:44.328142046Z     ns main err code: 12537
2025-09-08T16:49:44.328147957Z     
2025-09-08T16:49:44.328153908Z TNS-12537: TNS:connection closed
2025-09-08T16:49:44.328159839Z     ns secondary err code: 12560
2025-09-08T16:49:44.328165690Z     nt main err code: 507
2025-09-08T16:49:44.328171571Z     
2025-09-08T16:49:44.328177392Z TNS-00507: Connection closed
2025-09-08T16:49:44.328183242Z     nt secondary err code: 0
2025-09-08T16:49:44.328189143Z     nt OS err code: 0
2025-09-08T16:49:44.328195024Z 2025-09-08T16:49:43.882815+00:00
2025-09-08T16:49:44.328201035Z opiodr aborting process unknown ospid (5194) as a result of ORA-609
2025-09-08T16:50:09.330323086Z 2025-09-08T16:50:08.491544+00:00
2025-09-08T16:50:09.330357790Z 
2025-09-08T16:50:09.330366556Z

原因分析

首先由于docker内有日志说明连接是成功的,并且通过完整的docker虚拟地址可以正常访问,所以排除映射端口的问题。在日志中可以看到关键词ORA-609这个报错的意思是在规定时间内未能完成tns认证,出于安全原因断开连接,这是因为有一种半开连接的攻击可以撑爆内存,这是缓解措施。但是这次的问题与安全无关,只是这个措施也避免了一直卡住而一点报错也没有,这也算是不幸中的万幸。关注可以通过本机ip和虚拟地址访问而无法使用回环地址访问这个特征,我认为可能是访问地址在回环地址未能被正确转发或者路由。考虑到建立tcp连接成功了,但是在第二步tns出现问题,所以问题出在listener建立连接后与其他模块的通信。这里需要考虑一个通信机制:Out-of-Band breaks (OOB) 这个机制深入使用了本地回环网络,但是在docker中环境相对不同,docker有一套独立与主系统的本地回环,但是从主机访问时发送的包是本地回环数据包,tns模块在接收到包后回复也是使用的本地回环,但是这个包并非docker能够自动转发的标准包,而是一个包含包是否紧急等元信息的魔改版本的包,这使得回复未能转发并抵达连接端,于是卡在这里了。这个问题可以通过关闭oob机制来规避,强制所有的通信都使用标准的数据包来解决问题。

解决方案

这个方案带来的是部分紧急操作的性能损失,但基本可以忽略不计。

# 1. 进入运行Oracle数据库的容器
# 将 <container_name_or_id> 替换为实际的容器名称或ID
docker exec -it <container_name_or_id> /bin/bash

# 2. 切换到Oracle用户(通常容器内以oracle用户运行数据库)
su - oracle

# 3. 编辑 sqlnet.ora 文件。如果文件不存在,则新建它。
vi $ORACLE_HOME/network/admin/sqlnet.ora

# 4. 在文件中添加或修改以下行
DISABLE_OOB=ON

# 5. 保存并退出编辑器

# 6. 重启Oracle监听器以使配置生效
lsnrctl stop
lsnrctl start

# 7. 退出容器
exit

备选解决方案

重新构建容器,让docker和宿主机共用同一个回环网络,这样做会使得docker没有隔离的网络,有一定的安全问题,相较于安全问题,损失性能是更佳选项。

sudo docker run -d \
  --name oracle19c \
  --network host \  # 主要修改:使用宿主机网络模式
  -e ORACLE_SID=ORCLCDB \
  -e ORACLE_PDB=ORCLPDB1 \
  -e ORACLE_PWD=xxxxxxxxxx \
  -e ORACLE_EDITION=standard \
  -e ORACLE_CHARACTERSET=AL32UTF8 \
  -v /opt/docker/oracle19c/oradata:/opt/oracle/oradata \
  registry.cn-hangzhou.aliyuncs.com/zhuyijun/oracle:19c
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值