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

奇怪的TNS-12560错误的分析思路

白鳝的洞穴 2020-01-09
3190


某天,老白接到客户的一个电话,需要到现场解决一个问题。客户的电话就是命令,于是放下手中的活,急忙赶往客户现场。到达客户现场后,客户反应本地的一个应用程序隔一段时间就报错,同时客户传来了一张报错的图片,如下所示:

从上图来看,客户端的应用程序报错信息是ORA-12560或者TNS-12560错误,通过oerr命令

得知该错误是协议适配器错误,既然是网络相关的错误,就建议客户收集了数据库的监听器日志、sqlnet.log文件以及数据库的alert日志文件,然后依次查看这些文件,都没有发现有用的线索。此时陷入了僵局。

客户反映该应用程序不通过tns访问数据库,是在数据库服务器上直接跑的,这样来说这个应用程序是通过beq访问的数据库。也就是应用程序不走网络监听访问数据库,而是通过进程间通信访问数据库,这样性能更高。

日志中没有线索,就到Oracle Support网站上查吧,查了半天,发现12560错误相关的问题都是发生在Windows平台上的,只有一两篇与UNIX环境有关,其中一篇   Creating Inside An Linux/Unix Process Huge Number (500 and higher)Of Connections Against Database Fails With Network Errors ORA-12157 OrORA-12560 (文档 ID 563237.1)介绍的是FD_FILESIZE限制了进程打开的文件描述符,在AIX平台下的限制是65536,解决该问题需要安装补丁,因临近假期,这个核心业务系统的数据库打补丁也不现实,只好作罢,此时又限入了僵局,头疼啊。

该如何解决这个问题呢,后来突然一想,如果真的是这个BUG导致的问题,那么这套系统运行了三年了,早该出问题了,这个报错应该不是这个问题引起的。看来这个文档所描述的问题可能和我们遇到的有所不同,不过既然文档中提到了资源限制的问题,也给了我们一些思路,那就先查一查应用程序属主的资源限制吧,检查结果如下

看到上面的输出似乎有点感觉了,一个小应用程序32MB内存应该足够用了,说明内存问题不大,那就剩下nofiles打开的文件数这块有点门路了。谈到nofiles参数,客户也想起来了,前阵子好像也出现过nofiles参数不足的问题,把这个参数加大到20000后,那个问题就解决了。基于这个现象,考虑再次加大这个参数也不是长久之计,最好还是能够弄清楚为什么这个应用会存在打开文件数超出限制的问题。

由于AIX平台没有安装lsof工具,生产环境安装该工具也不允许临时安装工具。幸亏aix上有一个procfiles工具,可以检查某个进程打开的文件的情况。那就拿procfiles工具查一下,这个命令的用法挺简单procfiles <pid>即可查看该进程打开的文件数,加上-n参数即可显示打开的文件名,于是通过procfiles –n pid查询了进程打开的文件数,结果如下

从上图可以看到进程号为2139056,应用程序的命令行为xxxx start,就是我们要分析的这个模块。当前打开的文件描述符的限制为20000而当时该命令显示打开的文件描述符有652个左右。过了一个小时再次查询居然达到900多个,照这样的速度下去,文件描述符一定很快会达到20000的限制,当达到20000的限制后,应用程序连接数据库的时候也需要打开文件句柄才能够与数据库进行通信,此时由于资源限制,无法打开句柄与数据库通信,就报了一个奇怪的错误12560 TNS:protocol adapter error。

好啦,原因找到了,就是大量打开的文件描述符,达到了资源限制,无法与数据库通信导致的。那么大量打开的文件是什么文件或者什么类型的文件呢,从上图来看,打开的文件是dev 65535,65535,在/dev目录下也不存在设备号为65535,65535的文件,好在procfiles命令的输出中提示了打开的文件类型为FIFO,这不就是先进先出的管道文件吗。

把这个发现告知应用程序的开发人员后,开发人员查看应用程序版本库后,得知是9月8号生产环境的应用程序增加了一个任务,在任务中有popen打开一个fifo管道发送数据的调用,这个调用结束后没有使用pclose函数来关闭这个管道,具体代码如下


上述代码中,读取的文件内容到变量sLine中,程序的553行判断当sLine的长度为0时,直接返回SUCCESS而没有pclose关闭文件句柄的操作。于是这个程序在运行一段时间后就会出现打开文件数超过nofiles限制而报错了。于是开发人员在555~556行之间添加一行pclose(fd)就可以解决问题。

修改后,通过一系列的编译、链接操作后,生成新的应用程序文件,替换到生产环境中去,启动新的应用程序,经过一段时间,通过procfiles命令,查看应用程序打开的文件句柄,发现只有3个打开的文件句柄,至此12560问题解决。


    这又是一个ULIMIT资源限制导致的故障,只是报错比较隐蔽,不容易找到问题的原因。类似的问题其实都需要我们去仔细分析一下出问题的应用到底打开了什么文件,而不是简单的通过把ulimit设成-1或者加大到足够大来解决,否则下一次再报错时候,可能导致更严重的后果。

最后修改时间:2020-01-09 11:56:42
文章转载自 白鳝的洞穴,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论