问题特征:
使用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

被折叠的 条评论
为什么被折叠?



