暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

再见!ora-03113!

恒生DBA公社 2021-04-21
4640
前言导读


内容的开始起始于一个经典的报错:ora-03113。

某年某月的某一天,PB系统早上做日初始化时报了个错:ORA-03113:end-of-file on communication channel


随即检查分析:

  • 数据库可以正常连接

  • 防火墙未配置超时参数,并且配置了sqlnet.expire_time=10

  • 检查数据库日志,发现数据库前一天晚上有重启过。

  • 经确认,数据库重启后,没有重启所有中间件和应用。


看到这里,原因似乎已经明确了,重启中间件&应用后,问题得到了解决。


我们顺带再来分析一波:

  • ORA-03113错误是什么意思?

    客户端与ORACLE服务进程的通信意外中断,即连接失效


  • 导致3113错误的原因是什么?

    1.防火墙超时限制

    2.网络中断

    3.数据库异常重启

    4.会话或进程被杀掉

    5. Bug等


  • 我们需要如何预防呢?

  • 中间件和数据库服务器最好在同网段

  • 注意防火墙的默认配置,避免连接因空闲时间过久而被中断

  • 确认数据库是否需要配置会话空闲超时参数,默认UNLIMITED

  • 配置sqlnet.expire_time,清除死连接,且避免连接空闲

  • 数据库关闭前先关闭中间件和应用,数据库意外关闭后需重启中间件和应用


至此,很多人会有疑问,sqlnet.expire_time到底是什么?竟有这么神奇的功效? 接下来,有请主角登出!



什么是expire_time


在oracle数据库的sqlnet.ora文件中可以配置很多连接相关的参数,expire_time参数就是其中之一。Sqlnet.ora文件默认位于$ORACLE_HOME/network/admin/目录下,如果不存在,直接手工创建一个名称为sqlnet.ora的文件即可。使用expire_time参数可以定义一个以分为单位的时间间隔,每次达到时间,都会发送探测包到客户端,如果客户端没有响应,即发现这个客户端与服务进程的连接已经断开,就会返回一个错误消息,并进一步通过PMON进程清除相应的服务进程,达到释放资源的目的。


为什么要用expire_time


通过expire_time的介绍可知,该参数的作用就是清除数据库的死连接。

死连接即是Dead Connection,是指因为网络中断、客户端掉电、客户端异常重启等原因导致断开的客户端与服务进程的连接,这种方式断开的连接会使未正常退出的会话及相应的资源继续残留下来。

使用sqlnet.expire_time参数就可以实现检测死连接并促使结束残留会话及服务进程退出。

设置expire_time为非0值,即设置DCD(Dead Connection Detection)之后,服务端进程会定期发送一个10字节左右的包到客户端,如果客户端能正常响应并发回响应包,则说明连接正常,服务进程会在下一次达到expire_time设置的时间后再一次发送检测包,如果客户端没有发回响应包,则当PMON下一次进行循环任务时(并非DCD触发的时间),会进行服务进程的终止及资源的释放。

需要注意的就是死连接与空闲连接是不同的,空闲连接是仍然能正常通信的连接,只是暂时空闲,而死连接是已经断开的或者说不存在的连接。


expire_time的限制


并非所有情况都适合设置sqlnet.expire_time参数,以下是使用该参数的一些限制:

不支持bequeathed connections;

不支持APPC/LU6.2协议;

增加少量的网络负载。


expire_time参数配置


在$ORACLE_HOME/network/admin/sqlnet.ora文件中设置该参数为非0整数,即可开启DCD。

格式如下:

sqlnet.expire_time = 10

默认情况下,sqlnet.ora文件中不包含该参数,这与设置sqlnet.expire_time为 0的作用相同,即不进行DCD。



测试DCD


1、测试环境:

Os:rhel 5.4 64bit

Oracle:11.2.0.3

2、配置服务端的sqlnet.ora

cat  $ORACLE_HOME/network/admin/sqlnet.ora

sqlnet.expire_time  = 1

TRACE_LEVEL_SERVER  = 16

TRACE_FILE_SERVER  = SERVER

TRACE_DIRECTORY_SERVER= tmp/trace             

DIAG_ADR_ENABLED=OFF

说明:只有红色的参数是开启DCD必要的参数,蓝色部分的参数是为了本次测试能追踪到连接的情况而设置的

配置该参数后reload 监听

3、在客户端开启一个连接到数据库

sqlplus  xue/oracle123oracle@xue

开启一个事务:

SQL> insert into  t2 values(1);

在数据库中查询到该会话:

       SID MACHINE              STATUS

----------  -------------------- --------

        12 WORKGROUP\TIANHAI-PC INACTIVE

查询该会话对应的进程号:

SQL> select spid  from v$process where addr = (select paddr from v$session where sid=12);

SPID

------------------------

10088

在系统上查询到该进程:

[oracle@xueol  admin]$ ps -ef|grep 10088

oracle   10088      1  0 14:46 ?        00:00:00 oraclexue (LOCAL=NO)

4、检查10088进程产生的trace文件:

[02-JUL-2014  14:46:58:155] niotns: Enabling CTO, value=60000 (milliseconds)

[02-JUL-2014  14:46:58:155] niotns: Enabling dead connection detection (1 min)

[02-JUL-2014  14:46:58:155] niotns:  listener  bequeathed shadow coming to life...

可以发现DCD已经enable,时间为1分钟

5、禁用掉服务端的网卡

当前会话报3113错误

insert into t2  values (2)

            *

第 1 行出现错误:

ORA-03113: 通信通道的文件结尾

进程 ID: 10728

会话 ID: 531 序列号: 289

6、查看跟踪文件

可以看到如下信息:

[02-JUL-2014  15:02:55:352] nstimstart: entry

[02-JUL-2014  15:02:55:352] nstimstart: starting timer at 02-JUL-2014 15:02:55

[02-JUL-2014  15:02:55:352] nstimset: entry

[02-JUL-2014  15:02:55:352] nstimset: normal exit

[02-JUL-2014 15:02:55:352]  nstimstart: normal exit

[02-JUL-2014  15:02:55:352] nsconbrok: timer created for connection

……

[02-JUL-2014  15:06:42:882] nstimarmed: entry

[02-JUL-2014  15:06:42:882] nstimarmed: timer is armed, with value 0

[02-JUL-2014  15:06:42:882] nstimarmed: normal exit

[02-JUL-2014  15:06:42:882] nstimclear: entry

[02-JUL-2014  15:06:42:882] nstimclear: normal exit

日志中可以看到nstimstart、nstim

7、大概2分钟后查看会话和进程都已不存在

说明:在没有配置DCD的情况下,直接禁用网卡后,原会话及进程仍然存在,即使之后配置了DCD,该会话和进程也不会被清理。


总结


1、配置sqlnet.expire_time参数可以开启DCD,清除死连接;

2、对于开启DCD之前产生的死连接,即使开启DCD之后也无法自动清除,只能人为干预;

4、禁用网卡可以造成死连接;

5、Expire_time参数定义的时间是检测间隔,真正的清理死连接工作是由PMON定期执行的。

6、死连接在被清除前,在v$session中的状态为INACTIVE。

7、配置DCD会增加额外的网络负载并可能造成一定的性能下降

8、DCD因为会造成客户端和服务端之间不断的发包,从而使空闲连接不再真正的空闲,导致原本可以空闲超时断开的连接无法再自动断开,最终导致会话数量上升,配合使用profile的idle_time参数可以避免这种情况。



文章转载自恒生DBA公社,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论