https://www.laoxiong.net/oracle_and_firewall.html
老熊 Oracle数据库管理 2009-04-20

最近有两次Oracle数据库故障与防火墙有关。这里的防火墙是硬件网络防火墙,而不是软件防火墙。

先说说简单的。一个运行在Windows系统上的Oracle 9i,客户端不能连接数据库,但是用tnsping测试没有问题。解决问题的办法很简单,但是我们仍然需要了解一下引起这个问题的原因。

这个问题首先得从客户通通过监听连接数据库的整个过程说起,此处指专用服务器连接模式:

  • 服务器上的监听进程在1521端口上进行侦听
  • 客户端发起一个数据库连接请求
  • 监听进程fork一个Oracle服务器进程(Server Process),也可称之为影子进程 (Shadow Process)。服务器进程选择一个大于1024的端口号进行侦听,监听进程把这个端口号发回到客户端,要求客户端重新连接这个指定的端口。
  • 客户端重新连接监听指定的新端口,也就是重新进行连接。
  • 客户端与Server Process直接对话,不再通过监听,进行会话认证(登录),执行SQL等等。

从上述过程可以看到,客户端最终连接的端口实际上并不是1521。由于防火墙一般只开放了几个端口,对Oracle数据库只开放了1521端口,这样在客户端进行第二次连接时,不能通过防火墙,导致连接数据库失败。

值得庆幸的是,只有Windows平台上的9i及以下版本的Oracle才会有这个问题。Oracle在Linux以及Unix平台下,多个进程间可以对端口进行复用,Oracle Server Process仍然使用的是跟监听进程一个端口(1521)。通过在linux使用strace跟踪客户端连接数据库的过程可以发现,客户端只连接了一次,并没有进行第二次连接,与上面描述的流程相比已经发生了变化。在Windows平台上,10g及以上版本的库,也同样利用端口复用,避免了这样的问题。

那么Windows上运行的Oracle 9i怎么解决这个问题呢?答案很简单,在Windows注册表的\HKEY_LOCAL_MACHINE\SOFTWARE\ORACLE\HOMEn(这里n指Oracle Home的序号,只有一个Oracle Home时是0)键下面增加一项USE_SHARED_SOCKET,其值为TRUE。然后重启监听及Oracle服务(注意要重启Oracle的服务,而不仅仅是重启数据库),就可以解决此问题。实际上10g就是默认USE_SHARED_SOCKET为TRUE。

对于这种问题,或者是让防火墙打开针对数据库主机的所有端口访问,也能解决。但是这种方案往往会被负责安全的人否决。

下面这个由防火墙导致的问题,就相对复杂一点了。

某个应用经常报ORA-3113错误,检查发现ORA-3113来源于数据库的一个db link。为了方便下面的描述,将应用直接连接的数据库称为DB_A,DB_A通过db link连接的对端的数据库称为DB_B。在DB_B主机上没有发现任何有关的trace和日志,应用执行的SQL也是非常简单的SELECT语句,返回的数据量也不大。但出错的语句并不是固定的某一个SQL。在应用连接的数据库DB_A上做ORA-3113 error stack的trace,也没有发现有价值的东西。

导致ORA-3113错误的原因很多。大家可以参考ITPUB上的一篇贴子《ORA-03113错误分析》

在这个ORA-3113错误的问题中,数据库DB_B没有任何日志,出现这种情况的一个很可能的原因是,DB_B上的Server Process已经中止,但又不是在执行SQL过程中出错异常中止了,比如被KILL掉,网络连接中断等。被KILL掉这个原因,首先被排除,因为这个错误出现得很多,每天都有。询问维护人员,称也没有进行过KILL操作。那么最大的可能性应该是网络了。顺着这条线索,我们在DB_A上用netstat -na命令检查到DB_B的网络连接,与DB_B中v$session中的会话进行比较,发现DB_A连接到DB_B的数据库会话,比netstat 命令看到的网络连接数少得多。

这是一个重大的突破。首先要怀疑的是防火墙。因为防火墙导致Oracle连接异常的情况非常多。访问数据库的DBA,这两个数据库分别在不同的业务网络中,中间使用了Cisco的防火墙。请防火墙维护工程师检查防火墙的设置,发现防火墙设置了TCP连接超时(这个术语是防火墙工程师告诉给我的,实际上我个人认为这个术语字面含义跟其实际的作用相差较大)设置为1小时。也就是,对于通过防火墙的所有TCP连接,如果在1小时内没有任何活动,就会被防火墙拆除,这样就会导致连接中断。在拆除连接时,也不会向连接的两端发送任何数据来通知连接已经拆除。

而出问题的业务系统,使用的高峰期是在正常的工作时间内,最高时会导致DB_A会产生数十个连接到DB_B。但是在业务低谷期或经过一个晚上,防火墙将拆除大部分甚至是所有的连接。而下一次使用时,应用通过连接池选择DB_A中的一个会话,这个会话的db link之前已经连接到DB_B,但是网络连接已经被防火墙拆除,但是这个会话并不知道,仍然会认为这个连接有效,结果试图向DB_B提交SQL时,就出现了ORA-3113错误。

实际上,很多使用网络连接的应用,可以使用称之为KeepAlive的特性,来保持TCP连接的活动性。在打开一个连接时,通过setsockopt函数,设置socket为SO_KEEPALIVE,这样,在OS层,如果一个TCP连接在指定的时间内没有活动,会发送一个探测包到连接的对端,检测连接的对端是否仍然存在。如果这个时间小于防火墙中设置的“超时”时间,防火墙就会检查到连接中仍然有数据,就不会断开这个连接。

操作系统中keep alive的相关设置,不同的系统有不同的设置方法。比如在Linux中,在sysctl中设置net.ipv4.tcp_keepalive_time = 120,表示探测时间为120秒,即2分钟。在AIX中,通过no命令将tcp_keepidle参数设置为240,表示探测时间为120秒。注意AIX中这个参数的单位是1/2秒,而在Linux中是1秒。

不幸的是,通过在Linux和AIX上对Oracle进行跟踪发现,Oracle客户端连接数据库时(包括Oracle Server作为客户端连接DB LINK上的数据库),并没有在TCP Socket上打开SO_KEEPALIVE,因此不能通过设置操作系统的tcp keep alive的设置来解决此问题。

(Update 2009-08-06:在对监听的跟踪时发现,连接时客户端没有设置SO_KEEPALIVE,但是Server Process却对TCP Socket设置了SO_KEEPALIVE属性。)

还好Oracle提供了类似的机制。也就是DCD(Dead Conneciton Detection)。在$ORACLE_HOME/network/admin/sqlnet.ora文件中增加如下一行:

sqlnet.expire_time=NNN

这里NNN为分钟数,Oracle数据库会在会话IDLE时间超过这个指定的时间时,检测这个会话的对端(即客户端)是否还有效。避免客户端由于异常退出,导致会话一直存在。

因此,我们可以通过在DB_B数据库中的sqlnet.ora文件中设置expire_time来解决上面提到的ORA-3113问题。

关于Tcp KeepAlive,DCD以及防火墙,可参考metalink的文档257650.1

 
 

[转帖]Oracle与防火墙的更多相关文章

  1. 在Linux系统下远程连接oracle的防火墙设置

    在Linux系统要远程连接Oracle的防火墙设置方法: 打开5801至5810 端口用于vnc iptables -I INPUT -p tcp --dport 5801:5810 -j ACCEP ...

  2. [转帖]Oracle 11G RAC For Windows 2008 R2部署手册

    Oracle 11G RAC For Windows 2008 R2部署手册(亲测,成功实施多次) https://www.cnblogs.com/yhfssp/p/7821593.html 总体规划 ...

  3. [转帖]Oracle 补丁体系(PSR/PSU/CPU) 及 opatch 工具 介绍

    Oracle 补丁体系(PSR/PSU/CPU) 及 opatch 工具 介绍 原文:http://blog.csdn.net/tianlesoftware/article/details/58095 ...

  4. [转帖]Oracle 各个版本的升级路线图

    从oracle 7开始(甚至更早版本)到oracle 9iR2. 来源: https://blog.csdn.net/cymm_liu/article/details/11647533 http:// ...

  5. [转帖]Oracle 12cR2使用经验

    大规模升级来临,谈谈Oracle 12cR2使用经验 随着2019年2月13日,Oracle 19c (Oracle 12.2.0.3) for Exadata 版本发布,Oracle 12cR2体系 ...

  6. [转帖]Oracle 裁员史:技术人死于重组,卒于云计算

    Oracle 裁员史:技术人死于重组,卒于云计算 https://www.infoq.cn/article/tm-mcdHCPCI4eEwr6dbY 大厂裁员 我妈妈也总担心我没工作了 怎么还房贷 田 ...

  7. [转帖]oracle改版sql server问题点汇总

    https://www.cnblogs.com/zhangdk/p/oracle_sqlserver.html 只记得 最开始的时候看过 没有具体的了解里面的特点 原作者总结的很好 留下来 以后说不定 ...

  8. 转帖 Oracle 主键的处理方法 http://www.cnblogs.com/Richardzhu/p/3470929.html

    Oracle之主键的创建.添加.删除操作   一.创建表的同时创建主键约束 1.1.无命名 SQL> create table jack (id int primary key not null ...

  9. [转帖] Oracle数据库 通过触发器 限制登录ip

    转帖 From https://yq.aliyun.com/ziliao/123360 create or replace trigger logon_ip_control after logon o ...

  10. [转帖]Oracle字符集的查看与修改 --- 还未尝试 找个周六 试试.

    Oracle 字符集的查看和修改 感谢原作者 改天试试 https://www.cnblogs.com/rootq/articles/2049324.html 一.什么是Oracle字符集 Oracl ...

随机推荐

  1. 神经网络优化篇:梯度检验应用的注意事项(Gradient Checking Implementation Notes)

    梯度检验应用的注意事项 分享一些关于如何在神经网络实施梯度检验的实用技巧和注意事项. 首先,不要在训练中使用梯度检验,它只用于调试.意思是,计算所有\(i\)值的\(d\theta_{\text{ap ...

  2. 最大伪森林——kruskal算法活用 (HDU - 3367)

    最大伪森林--kruskal算法活用 (HDU - 3367) kruskal这一用来求生成树的算法,经过修改拓展之后,可以求很多种形式的子图,本题(HDU3367)即为一个应用案例 单击进入原题 以 ...

  3. SaaS 营销,如何利用 RPA 实现自动化获客?

    大家好,这次给大家带来如何利用 RPA 实现自动化获客. 一.RPA 是什么?难吗? RPA 对大家来说,可能挺陌生的,其实它很简单. Robotic Process Automation(简称 RP ...

  4. 1024 | 9位开发者分享生涯“最”时刻,文武状元大PK等你来

    本文分享自华为云社区<1024程序员节,和华为云一起做不被定义的开发者>,作者:华为云社区精选 . 1024,祝所有开发者们节日快乐 "代码有注释,程序无bug, 需求不改动,永 ...

  5. 共筑数字化未来,金山办公携手华为云完成文档中心和GaussDB适配

    摘要:金山办公携手华为云完成金山办公自主研发的"WPS文档中心系统"与华为云GaussDB相互兼容性测试认证,并获得华为云授予的<技术认证书>. 本文分享自华为云社区& ...

  6. LiteOS内核源码分析:消息队列Queue

    摘要:本文通过分析LiteOS队列模块的源码,掌握队列使用上的差异. 队列(Queue)是一种常用于任务间通信的数据结构.任务能够从队列里面读取消息,当队列中的消息为空时,挂起读取任务:当队列中有新消 ...

  7. CG行业云渲染服务的演进之路

    摘要:影视动画.特效制作等行业渲染需求量增多,4K/6K以及各高分辨率会陆续成为主流,本地算力与存储资源已无法满足现有任务量.而随着大环境的演变,CG行业发展已进入发展快车道.来自赞奇科技的CEO金伟 ...

  8. 手绘流程图讲解spark是如何实现集群的高可用

    摘要:本文讲述spark是怎么针对master.worker.executor的异常情况做处理的. 本文分享自华为云社区<图解spark是如何实现集群的高可用>,作者:breakDawn. ...

  9. 火山引擎 DataTester 科普:A/B 实验常见名词解释

    DataTester 是字节跳动在 2019 年正式通过火山引擎数智平台推出的对外服务的 A/B 实验工具,它基于先进的底层算法,提供科学分流能力,提供智能的统计引擎,实验结果可靠有效,助力业务决策. ...

  10. Solon 编译打包怎样保持参数名不变?

    1.Java 项目 Java maven 项目 <plugin> <groupId>org.apache.maven.plugins</groupId> <a ...