Oracle DCD和Linux TCP KeepAlive和网络硬件防火墙探讨
Oracle DCD和Linux TCP KeepAlive和网络硬件防火墙探讨
Oracle的某些会话在超时断开后在警告日志抛出一定量类似如下日志:
Fri Aug 19 17:51:32 2022 *********************************************************************** Fatal NI connect error 12170. VERSION INFORMATION: TNS for Linux: Version 11.2.0.4.0 - Production Oracle Bequeath NT Protocol Adapter for Linux: Version 11.2.0.4.0 - Production TCP/IP NT Protocol Adapter for Linux: Version 11.2.0.4.0 - Production Time: 19-AUG-2022 17:51:32 Tracing not turned on. Tns error struct: ns main err code: 12535 TNS-12535: TNS:operation timed out ns secondary err code: 12560 nt main err code: 505 TNS-00505: Operation timed out nt secondary err code: 110 nt OS err code: 0 Client address: (ADDRESS=(PROTOCOL=tcp)(HOST=192.168.1.14)(PORT=57791))
咨询网络管理员,得到如下回复:
1.同个机房之间不经过防火墙;
2.区域A和区域B(跨机房)之间经过硬件防火墙,长连接超时设置如下: 从A->B,1天;从B->A,15天;
3.区域A,B之间细粒度是机房的,任何数据库,应用等产生网络数据均会刷新长连接计时,,,,,,实际上每时每刻均会有数据交互。
上诉提到的会话S1报错是跨机房的,报错时间是2022-08-19 17:51:32,查看S1会话的监听日志发现该会话是2022-05-23 17:25:46建立连接的。
相差了3个月左右。
<msg time='2022-05-23T17:25:46.561+08:00' org_id='oracle' comp_id='tnslsnr' type='UNKNOWN' level='16' host_id='xxxxdb1' host_addr='192.168.1.51'> <txt>23-MAY-2022 17:25:46 * (CONNECT_DATA=(SERVICE_NAME=xxxxdb)(CID=(PROGRAM=C:\Program?Files\PLSQL?Developer?14\plsqldev.exe)(HOST=MACHINE02)(USER=zhaokm))) * (ADDRESS=(PROTOCOL=tcp)(HOST=192.168.1.14)(PORT=57791)) * establish * xxxxdb * 0 </txt> </msg>
目前可以排除网络硬件防火墙设置导致会话断开。
查看其他数据库2022-08-19 17点左右的日志,核心库也存在大量的日志报错。
且OEM有大量提示无法检测到数据库的报警,判断是网络引起的问题。
实际除了防火墙,Linux OS本身也存在TCP的保活机制。
摘自:https://blog.csdn.net/qq_27706119/article/details/128734024
Linux内核自带的保活机制keep-alive。使用的时候只需要打开keep-alive功能即可。
TCP的Keepalive机制的作用是在于探测连接的对端是否存活。
工作原理:TCP keep-alive是通过在空闲时发送TCP Keep-Alive数据包,然后对方回应TCP Keep-Alive ACK来实现的。
在socket网络编程中,需要设置一个socket选项 SO_KEEPALIVE,才能开启keepalive机制。
在Linux的keepalive机制中,有3个重要的内核参数:tcp_keepalive_time、tcp_keepalive_probes 和 tcp_keepalive_intvl。
tcp_keepalive_time:表示TCP连接闲置多长时间后开始发送探测报文。(单位:秒)
tcp_keepalive_probes:表示一次探测过程中最多可以重发探测报文的次数。(没有收到确认时重发次数)
tcp_keepalive_intvl:表示前一个探测报文和后一个探测报文之间的时间间隔。(即超时重传的时间间隔)(单位:秒)
测试的时候调整为比较小的时间进行观察:
sysctl -w net.ipv4.tcp_keepalive_time=60
sysctl -w net.ipv4.tcp_keepalive_probes=2
sysctl -w net.ipv4.tcp_keepalive_intvl=10
使用PLSQL Developer远程发起一个连接到数据库,使用ss或者netstat命令查看客户端会话信息,可以明显看到keppalive的计时,如下:
[root@oracle1 ~]# ss -o state established ' dst 192.168.2.189 ' | grep -v ssh Recv-Q Send-Q Local Address:Port Peer Address:Port 0 0 192.168.1.47:ncube-lm 192.168.2.189:52193 timer:(keepalive,47sec,0) [root@oracle1 ~]# netstat -anptwo | grep 192.168.2.189 | grep -v ssh tcp 0 0 192.168.1.47:1521 192.168.2.189:52193 ESTABLISHED 11299/oracleqadb1 keepalive (44.91/0/0)
因此,实际在OS层面已经确保会话默认2h内不会断开。
再说说Oracle DCD(死连接检测,即Dead Connection Detection),用于检查那些死掉但没有断开的session。
当设置了SQLNET.EXPIRE_TIME,定时器会根据设置的值定期向会话发送侦测包来确定会话是否已经异常断开。
详情可见:Archived: Dead Connection Detection (DCD) Explained (Doc ID 151972.1)
根据我查看的一些资料,比如老熊的两篇文章:Oracle与防火墙、防火墙、DCD与TCP Keep alive
里边有提到,设置DCD会导致关闭了TCP本身的keep-alive功能,且本身DCD也无法生效。
比如设置DCD为1分钟,
[oracle@oracle1 admin]$ cat sqlnet.ora SQLNET.EXPIRE_TIME= 1
使用PLSQL Developer重新发起一个连接到数据库,使用ss或者netstat命令查看客户端会话信息,会发现无法获取到keppalive的信息了。
[root@oracle1 ~]# ss -o state established ' dst 192.168.2.189 ' | grep -v ssh Recv-Q Send-Q Local Address:Port Peer Address:Port 0 0 192.168.1.47:ncube-lm 192.168.2.189:58126 [root@oracle1 ~]# netstat -anptwo | grep 192.168.2.189 | grep -v ssh tcp 0 0 192.168.1.47:1521 192.168.2.189:58126 ESTABLISHED 8518/oracleqadb1 off (0.00/0/0) [root@oracle1 ~]#
同时,使用service network stop断开网络连接,发现几分钟内也没有回收PLSQL Developer的会话。
ss和netstat查看信息,会发现存在计时,且为0后重新从2分钟倒计时..循环这个过程。
[root@oracle1 Desktop]# ss -o state established ' dst 192.168.2.189 ' | grep -v ssh Recv-Q Send-Q Local Address:Port Peer Address:Port 0 80 192.168.1.47:ncube-lm 192.168.2.189:58126 timer:(persist,25sec,11) [root@oracle1 Desktop]# ss -o state established ' dst 192.168.2.189 ' | grep -v ssh Recv-Q Send-Q Local Address:Port Peer Address:Port 0 80 192.168.1.47:ncube-lm 192.168.2.189:58126 timer:(persist,22sec,11) [root@oracle1 Desktop]# netstat -anptwo | grep 192.168.2.189 | grep -v ssh tcp 0 80 192.168.1.47:1521 192.168.2.189:58126 ESTABLISHED 8518/oracleqadb1 probe (19.25/0/11) [root@oracle1 Desktop]# netstat -anptwo | grep 192.168.2.189 | grep -v ssh tcp 0 80 192.168.1.47:1521 192.168.2.189:58126 ESTABLISHED 8518/oracleqadb1 probe (7.98/0/11) [root@oracle1 Desktop]# netstat -anptwo | grep 192.168.2.189 | grep -v ssh tcp 0 80 192.168.1.47:1521 192.168.2.189:58126 ESTABLISHED 8518/oracleqadb1 probe (119.96/0/12) [root@oracle1 Desktop]# ss -o state established ' dst 192.168.2.189 ' | grep -v ssh Recv-Q Send-Q Local Address:Port Peer Address:Port 0 80 192.168.1.47:ncube-lm 192.168.2.189:58126 timer:(persist,1min58sec,12)
BUG还是很多的,DCD。
参考:
ORACLE的Dead Connection Detection浅析
https://www.cnblogs.com/chhyan-dream/p/16226134.html
How to Check if Dead Connection Detection (DCD) is Enabled in 9i ,10g and 11g (Doc ID 395505.1)
Versions 11, 12 and Newer Databases: Fatal NI Connect Error 12170, 'TNS-12535: TNS:operation timed out' Reported in Alert Log (Doc ID 1286376.1)