Welcome 微信登录

首页 / 数据库 / MySQL / 原来是它(Oracle.ManagedDataAccess.Client)——再说ORA-12516故障解决

最近一直和ORA-12516报错作斗争。接着我之前分享的一篇文章说起  http://www.linuxidc.com/Linux/2015-06/119139.htm,当时通过kill进程的方法临时解决了问题,但是根本问题没有找到——为什么设备会产生大量连接?说到底,这个问题当时并没有解决,并且继续“折磨”了我将近一个月。这段时间,不断地有人找我——数据库连不上了!!!问题到底出在哪儿了呢。下面和大家分享一下解决过程,希望对大家有所借鉴。开发环境
操作系统:Windows Server 2008 R2  Standard
数据库:Oracle 10g(10.2.0.4) 64bit频繁报错ORA-12516,初步分析
最近ORA-12516错误频出,我也是不胜其烦。但是每次都找不到根本原因,只能停监听、杀进程或者直接关闭客户端程序。
 复述一下故障现象:连接数据库报错,提示“ORA-12516”错误——“ORA-12516: TNS: 监听程序无法找到匹配协议栈的可用句柄”。一直很稳定的系统架构,为什么突然不行了呢?
 数据库processes参数使用的默认值150,相应的sessions为170,;
 我们采用C/S架构,其中Client数量并不多,也就20台左右,所以正常情况下sessions数量为40左右,其中包括16个数据库内部连接。
 可现在,sessions数量动辄就到了130~140,直接导致ORA-12516报错。下面贴一个当时的查询结果:SQL> set pagesize 150
 
SQL> set linesize 200SQL> col username for a10SQL> col terminal for a20SQL> col program for a20SQL> select username,program,terminal,count(*) from v$session group by rollup(username,program,terminal);USERNAME PROGRAM TERMINAL COUNT(*)---------- -------------------- -------------------- ----------......此处省略内容
         ORACLE.EXE (q000) 1          ORACLE.EXE (q001) DBSERVER 1          ORACLE.EXE (q001) 1                                                            16SYS sqlplus.exe DBSERVER 1SYS sqlplus.exe 1SYS 1HOEGH HOEGH.exe Client7 1HOEGH HOEGH.exe CLIENT2 95HOEGH HOEGH.exe Client3 1HOEGH HOEGH.exe Client4 2HOEGH HOEGH.exe CLIENT5 28HOEGH HOEGH.exe Client6 1HOEGH HOEGH.exe 128HOEGH 128                                                         145
可以看出,CLIENT2 和CLIENT5 两个终端的连接数分别为95和28,肯定有问题。查询session,尝试定位故障设备
通过select username,program,terminal from v$sessions;查询数据库连接,看到某一台或者某两台的session数达到30,有的甚至超过70。把相应设备的应用程序(应用程序连接数据库)重启后,问题有时能迅速缓解,有时却没有效果。
 起初是怀疑Client设备的硬件或者操作系统,因为这些设备中的操作系统比较杂(实验室为了测试方便),包括32位的Windows XP、32位及64位的Win7,还有64位的Win8。后来经过长时间的观察,发现故障设备并不固定,也就是说,每一台设备都有可能成为“故障设备”。有点迷茫了。C#清空连接池
经过长时间观察及初步分析,得出的结论是这个问题可能与具体设备没有直接关系,而是和目前的数据库断连判断代码有关。我们的应用程序为了显示数据库连接状态,定时去连接数据库,起到“心跳”的作用。我们怀疑是不是每台设备都这么去频繁连接数据库,而这些连接却没有释放,时间长了session数量就上去了,于是在代码中添加了清空连接池的语句。但是,没有效果。其实,现在是怀疑一切了,因为以往项目我们采取的是同样的数据库“心跳”机制,一直没有出过问题。添加静态监听
后来一直在网上查这个ORA-12516,不少朋友提到了通过监听去发现、解决问题。我看了一下数据库服务器的监听日志Listener.log,好家伙,都80多M了,记事本都打不开了。最后用UE打开监听日志,发现里面大片的TNS-12514报错。10-6月 -2015 16:26:53 * service_update * hoegh * 0
 
10-6月 -2015 16:26:56 * (CONNECT_DATA=(CID=(PROGRAM=)(HOST=__jdbc__)(USER=))(SERVICE_NAME=hoegh)) * (ADDRESS=(PROTOCOL=tcp)(HOST=192.168.3.191)(PORT=50641)) * establish * hoegh * 12514TNS-12514: TNS: 监听程序当前无法识别连接描述符中请求的服务10-6月 -2015 16:26:58 * (CONNECT_DATA=(CID=(PROGRAM=)(HOST=__jdbc__)(USER=))(SERVICE_NAME=hoegh)) * (ADDRESS=(PROTOCOL=tcp)(HOST=192.168.3.191)(PORT=50644)) * establish * hoegh * 12514TNS-12514: TNS: 监听程序当前无法识别连接描述符中请求的服务10-6月 -2015 16:26:58 * (CONNECT_DATA=(CID=(PROGRAM=)(HOST=__jdbc__)(USER=))(SERVICE_NAME=hoegh)) * (ADDRESS=(PROTOCOL=tcp)(HOST=192.168.3.191)(PORT=50645)) * establish * hoegh * 12514TNS-12514: TNS: 监听程序当前无法识别连接描述符中请求的服务10-6月 -2015 16:26:58 * (CONNECT_DATA=(CID=(PROGRAM=)(HOST=__jdbc__)(USER=))(SERVICE_NAME=hoegh)) * (ADDRESS=(PROTOCOL=tcp)(HOST=192.168.3.191)(PORT=50647)) * establish * hoegh * 12514TNS-12514: TNS: 监听程序当前无法识别连接描述符中请求的服务10-6月 -2015 16:26:58 * (CONNECT_DATA=(CID=(PROGRAM=)(HOST=__jdbc__)(USER=))(SERVICE_NAME=hoegh)) * (ADDRESS=(PROTOCOL=tcp)(HOST=192.168.3.191)(PORT=50648)) * establish * hoegh * 12514TNS-12514: TNS: 监听程序当前无法识别连接描述符中请求的服务10-6月 -2015 16:27:08 * service_update * hoegh * 010-6月 -2015 16:27:09 * (CONNECT_DATA=(SERVICE_NAME=hoegh)(CID=(PROGRAM=D:\HOEGHATS\HOEGH.exe)(HOST=)(USER=Administrator))) * (ADDRESS=(PROTOCOL=tcp)(HOST=3.16.11.50)(PORT=4528)) * establish * hoegh * 0
根据大家的建议,我尝试在监听配置文件Listener.ora中添加了静态监听,其中黄色部分为新添加内容。
但是,效果不大。SID_LIST_LISTENER =
 
  (SID_LIST = (SID_DESC =   (SID_NAME = PLSExtProc)   (ORACLE_HOME = c:\oracle\product\10.2.0\db_1)   (PROGRAM = extproc) ) (SID_DESC =   (SID_NAME = hoegh)   (ORACLE_HOME = c:\oracle\product\10.2.0\db_1) )
  )LISTENER =(DESCRIPTION_LIST = (DESCRIPTION =   (ADDRESS = (PROTOCOL = TCP)(HOST = DBSERVER)(PORT = 1521))   (ADDRESS = (PROTOCOL = IPC)(KEY = EXTPROC0)) ))增大processes初始化参数
黔驴技穷,我又使了这招,可是丝毫不起作用,不同的是以往连接总数是一百三四十,现在增加到了二百七八十,问题依旧。
 结合上面的静态监听,我再次查看listener.log,发现大量TNS-12518和TNS-12560报错,以及少量的TNS-12514报错:15-6月 -2015 15:39:13 * 12502
 
TNS-12502: TNS: 监听程序没有从客户机收到 CONNECT_DATA15-6月 -2015 15:39:13 * (CONNECT_DATA=(SERVICE_NAME=hoegh)(CID=(PROGRAM=D:\HOEGHATS\HOEGH.exe)(HOST=CLIENT5)(USER=work))) * (ADDRESS=(PROTOCOL=tcp)(HOST=3.16.210.94)(PORT=55359)) * establish * hoegh * 12518TNS-12518: TNS: 监听程序无法分发客户机连接TNS-12560: TNS: 协议适配器错误15-6月 -2015 15:39:13 * (CONNECT_DATA=(SERVICE_NAME=hoegh)(CID=(PROGRAM=D:\HOEGHATS\HOEGH.exe)(HOST=)(USER=JDWL))) * (ADDRESS=(PROTOCOL=tcp)(HOST=3.20.16.50)(PORT=2200)) * establish * hoegh * 12518TNS-12518: TNS: 监听程序无法分发客户机连接TNS-12560: TNS: 协议适配器错误15-6月 -2015 15:39:13 * (CONNECT_DATA=(SERVICE_NAME=hoegh)(CID=(PROGRAM=D:\HOEGHATS\HOEGH.exe)(HOST=DISPATCHER1)(USER=work))) * (ADDRESS=(PROTOCOL=tcp)(HOST=3.16.210.92)(PORT=50761)) * establish * hoegh * 12518TNS-12518: TNS: 监听程序无法分发客户机连接TNS-12560: TNS: 协议适配器错误15-6月 -2015 15:39:13 * 12502TNS-12502: TNS: 监听程序没有从客户机收到 CONNECT_DATA15-6月 -2015 15:39:13 * (CONNECT_DATA=(SERVICE_NAME=hoegh)(CID=(PROGRAM=D:\HOEGHATS\HOEGH.exe)(HOST=WINOW-BWMCG6U3V)(USER=JDWL))) * (ADDRESS=(PROTOCOL=tcp)(HOST=3.20.1.52)(PORT=3487)) * establish * hoegh * 12518TNS-12518: TNS: 监听程序无法分发客户机连接TNS-12560: TNS: 协议适配器错误15-6月 -2015 15:39:13 * (CONNECT_DATA=(SERVICE_NAME=hoegh)(CID=(PROGRAM=D:\HOEGHATS\HOEGH.exe)(HOST=ATSSERVER1)(USER=Administrator))) * (ADDRESS=(PROTOCOL=tcp)(HOST=3.16.210.74)(PORT=3404)) * establish * hoegh * 12518TNS-12518: TNS: 监听程序无法分发客户机连接TNS-12560: TNS: 协议适配器错误15-6月 -2015 15:39:13 * (CONNECT_DATA=(SERVICE_NAME=hoegh)(CID=(PROGRAM=D:\HOEGHATS\HOEGH.exe)(HOST=CLIENT2)(USER=Administrator))) * (ADDRESS=(PROTOCOL=tcp)(HOST=3.16.210.66)(PORT=2229)) * establish * hoegh * 12518TNS-12518: TNS: 监听程序无法分发客户机连接TNS-12560: TNS: 协议适配器错误重建监听器
重启设备是一个“大招”,以前碰到“疑难杂症”重启往往能够收到奇效。最后,我甚至都想着重建数据库了,不过考虑着动静有点大,可能会影响其他人工作,只好作罢;那我重建一下监听试一下吧。于是,我通过netca删除原有监听,重建监听程序listener,都采用默认配置。可是,问题依旧。更换微软驱动System.Data.OracleClient
真是没招了,最后和部门的架构师一起讨论这个问题,会不会和数据库驱动有关系呢。
 我们的应用程序是用C#开发的,连接数据库需要数据驱动支持,以前我们采用的是微软的数据库驱动System.Data.OracleClient,最近这个项目换成了Oracle官方驱动Oracle.ManagedDataAccess.Client。至于为什么要换,最主要是考虑Oracle官方驱动部署方便,无需安装Oracle数据库客户端。说干就干,把实验室的所有客户端设备的驱动都更换为System.Data.OracleClient,我再去查看session连接状况,看到输出结果哭了都快,session数真的好少啊!!!SQL> set pagesize 150
 
SQL> set linesize 200SQL> col username for a10SQL> col terminal for a20SQL> col program for a20SQL> select username,program,terminal,count(*) from v$session group by rollup(username,program,terminal);USERNAME PROGRAM TERMINAL COUNT(*)---------- -------------------- -------------------- ----------......此处省略内容          ORACLE.EXE (q000) 1          ORACLE.EXE (q001) DBSERVER 1          ORACLE.EXE (q001) 1                                                            16SYS sqlplus.exe DBSERVER 1SYS sqlplus.exe 1SYS 1HOEGH HOEGH.exe Client7 1HOEGH HOEGH.exe CLIENT2 1HOEGH HOEGH.exe Client3 1HOEGH HOEGH.exe Client4 2HOEGH HOEGH.exe CLIENT5 1HOEGH HOEGH.exe Client6 1HOEGH HOEGH.exe 7HOEGH 7                                                         24说到最后的话
这个问题折腾一个多月了,现在看似得到彻底解决,但是心里还是不踏实,毕竟Oracle官方驱动Oracle.ManagedDataAccess.Client还是有不少优点的。
• Oracle驱动部署方便,数据类型兼容性好,如Timestamp类型支持保存ms级数据(大家可以参考以前 http://www.linuxidc.com/Linux/2015-06/119141.htm);
• 微软驱动更加稳定,但是不再提供更新,无法支持一些新特性。那么,问题来了,会不会是我们的使用方法有问题呢,还请用过Oracle官方驱动Oracle.ManagedDataAccess.Client的朋友不吝赐教。更多Oracle相关信息见Oracle 专题页面 http://www.linuxidc.com/topicnews.aspx?tid=12本文永久更新链接地址