首页 » 数据库 » Oracle » 跨机房(跨防火墙)数据库访问超时问题分析TNS-12535、TNS-00505

跨机房(跨防火墙)数据库访问超时问题分析TNS-12535、TNS-00505

 

背景说明和问题描述

自从数据库迁移到其它机房后,应用经常反馈有会话超时的问题(而且会出现900多秒才返回超时报错的现象),虽然量很小,但也影响用户感知

而未割接的数据库访问一直无超时现象

两者的区别:异机房访问跨防火墙同机房访问不涉及防火墙

异常日志

2020-02-04T20:43:28.882055+08:00Fatal NI connect error 12170.VERSION INFORMATION:TNS for Linux: Version 12.2.0.1.0 - ProductionOracle Bequeath NT Protocol Adapter for Linux: Version 12.2.0.1.0 - ProductionTCP/IP NT Protocol Adapter for Linux: Version 12.2.0.1.0 - ProductionTime: 04-FEB-2020 20:43:28Tracing not turned on.Tns error struct:ns main err code: 12535TNS-12535: TNS:operation timed outns secondary err code: 12560nt main err code: 505TNS-00505: Operation timed outnt secondary err code: 110nt OS err code: 0Client address: (ADDRESS=(PROTOCOL=tcp)(HOST=*.*.*.*)(PORT=37852))  

分析过程

先说下思路,涉及数据库出现访问超时,无非考虑的几点

1、网络异常(防火墙层面)

2、数据库负载高,建立会话响应超时(数据库层面)

3、主机会话异常(主机层面)

防火墙层面:

因为是迁移到异机房后出现的超时问题,流量经过防火墙是唯一的变数,所以第一时间想到的是防火墙问题导致

从目前架构看,跨机房后涉及两种型号的防火墙:华为防火墙,华三防火墙

防火墙层对建立的会话有过期策略,华为防火墙默认20分钟,华三防火墙默认1小时

也就是说,如果业务在访问数据库时,如果会话停留超过20分钟无流量交互,防火墙会主动将会话断开

这是防火墙层面的超时机制,通过修改防火墙会话过期策略,可以解决超时问题

此类会话在主机层面是以非正常TCP策略断开,属于异常会话,而主机有针对异常会话的回收机制

主机层面:

主机层面提供针对会话存活的探测机制:tcp_keepalive

[root ~]# sysctl -a | grep keepalive(默认配置)net.ipv4.tcp_keepalive_time = 7200  #代表每隔7200s发起ack探测net.ipv4.tcp_keepalive_probes = 9   #探测频次,如果超过9次对方无ack响应,第10次发送rstnet.ipv4.tcp_keepalive_intvl = 75   #每次相隔75s发送一次ack  

当防火墙将会话过期后,主机在2个小时后会按时发起ack探测包

而在防火墙会话没有过期时,假设net.ipv4.tcp_keepalive_time=960,则主机每16分钟发送一次ack探测包,防火墙会话过期倒计时会重置

针对两种结果的得出的结论:

1)如果net.ipv4.tcp_keepalive_time >= 防火墙会话过期时间,会话会正常被防火墙过期,keepalive探测发现后,会正常中断进程,回收资源

2)如果net.ipv4.tcp_keepalive_time < 防火墙会话过期时间,keepalive机制正常发送ack探测包,防火墙会话过期倒计时会被重置,会话一直处于active状态

数据库层面:

提取问题时间点的awr和主机性能报告分析,并未出现负载高峰

涉及监听链接超时设置虽然默认值,但从应用反馈的情况来看,业务是dblink访问的(长链接),跟此参数影响不大

从上面防火墙和主机分析来看,是由于防火墙会话过期导致,针对这种情况,Oracle数据库也提供了一种会话存活探测机制:DCD(dead connection detection)

具体设置方法:

vi $ORACLE_HOME/network/admin/sqlnet.oraSQLNET.EXPIRE_TIME=10   <br>#代表的意思是会话处于inactive 10分钟后,服务端会发送10字节的小包到客户端,进行存活探测,如果无响应,则会话关闭,资源回收 

需要注意的是:

1)如果SQLNET.EXPIRE_TIME设置时间小于防火墙会话超时限制,防火墙会话会一直保持active状态,不会发生过期

2)如果SQLNET.EXPIRE_TIME设置时间大于防火墙会话超时限制,防火墙会话过期就会正常发生,此时数据库实例会探测到会话异常,并且正常关闭链接,回收资源

针对应用经常出现900多s才返回超时报错日志的问题:

该问题是由系统参数tcp_retries2的设置决定的

该参数表示在丢弃激活(已建立通讯状况)的TCP连接之前﹐需要进行多少次重试。默认值为15

该参数的值是根据RTO值来的,一般响应超时时间为retransmit N次=(N+1)th RTO,默认15次,需要924s

在系统优化时,该参数建议设置为5

总结

为了避免数据库跨防火墙访问出现超时,可以做如下优化:

1、调整防火墙会话过期策略,明确来源IP,目标IP,目标端口,避免范围过大,在线会话过多,影响防火墙性能

2、主机keepalive合理设置,如果防火墙会话过期策略不能调整,建议设置小于防火墙会话超时时间

3、数据库启用DCD策略,设置值小于防火墙会话超时时间

原文链接:跨机房(跨防火墙)数据库访问超时问题分析TNS-12535、TNS-00505,转载请注明来源!

1