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. JavaFx之触发激发鼠标事件(二十三)

    JavaFx之触发激发鼠标事件(二十三) 有时候,我们不能直接触发/激发某个按钮的点击事件,因为发起方可能是子线程.使用屏幕点击又不优雅,javafx已经提供了事件的激发,即使在子线程中也能激发某个按 ...

  2. 中文语音识别转文字的王者,阿里达摩院FunAsr足可与Whisper相颉顽

    君不言语音识别技术则已,言则必称Whisper,没错,OpenAi开源的Whisper确实是世界主流语音识别技术的魁首,但在中文领域,有一个足以和Whisper相颉顽的项目,那就是阿里达摩院自研的Fu ...

  3. 如何使用loki查询日志中大于某一数字的值的日志

    简介 loki是一款轻量级的日志收集中间件,比elk体系占用的内存更小,采用go语言开发,可以利用grafana来查询loki中存储的日志,loki存储日志只对提前预设的标签做索引,所以日志存储空间占 ...

  4. 如何将没有复制或移动构造函数的对象放入vector容器

    正文 直接说答案,这个问题无法实现.原因是因为std::vector容器的插入一定会调用类对象的构造函数或者移动构造函数. 说一下为什么会有这个问题,因为不想用指针,我想直接通过类对象本身的RAII机 ...

  5. Nignx快速入门

    Nginx快速入门 一.简介 产生的背景:当一台服务器同一时刻被大量客户端请求访问时,访问量超出服务器请求范围,服务器处理不过来,发生宕机或者丢失连接情况下,产生了Nignx反向代理技术. Nginx ...

  6. Axure 自定义元件库

    点击文件 -> 新建元件库 可以添加多个元件,并将期重命名 保存元件库 新建页面 添加元件,选择自建的元件库 导入后就会发现我的原件库 这样就可以使用我们自定义的元件库了

  7. JS 实现 HashMap

    HashMap代码(这种实现方式是错误的,错误原因:代码中_map._length变量是HashMap的所有实例共用的): /** * HashMap * 2021年09月09日 */ (functi ...

  8. AcWing 第 2 场周赛

    比赛链接:Here AcWing 3626. 三元一次方程 暴力即可 void solve() { int n; cin >> n; for (int i = 0; i <= n / ...

  9. java向一个压缩包里增加文件

    如果遇到,向现有的压缩包里增加文件的需求可以参照如下的方式: 思路:1.先将压缩包解压 2.删除旧的压缩包 3.将解压后的文件和希望添加的文件一起重新生成一个压缩包 4.将第一步中解压后的文件删除. ...

  10. linux挂载磁盘和设置开机自动挂载

    1.查看分区信息 root@xmgl opt]# fdisk -l ......此处省略一些信息 Disk /dev/sdb: 644.2 GB, 644245094400 bytes, 125829 ...