首页 > 数据库技术 > 详细

原来是它(Oracle.ManagedDataAccess.Client)——再说ORA-12516故障解决

时间:2015-06-20 02:17:05      阅读:618      评论:0      收藏:0      [点我收藏+]
        最近一直和ORA-12516报错作斗争。接着我之前分享的一篇博文说起http://blog.itpub.net/30162081/viewspace-1623524/,当时通过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报错。

下面贴一个当时的查询结果:

点击(此处)折叠或打开

  1. SQL> set pagesize 150
  2. SQL> set linesize 200
  3. SQL> col username for a10
  4. SQL> col terminal for a20
  5. SQL> col program for a20
  6. SQL> select username,program,terminal,count(*) from v$session group by rollup(username,program,terminal);
  7.  
  8. USERNAME PROGRAM TERMINAL COUNT(*)
  9. ---------- -------------------- -------------------- ----------
  10. ......此处省略内容
  11.            ORACLE.EXE (q000) 1
  12.            ORACLE.EXE (q001) DBSERVER 1
  13.            ORACLE.EXE (q001) 1
  14.                                                              16
  15. SYS sqlplus.exe DBSERVER 1
  16. SYS sqlplus.exe 1
  17. SYS 1
  18. HOEGH HOEGH.exe Client7 1
  19. HOEGH HOEGH.exe CLIENT2 95
  20. HOEGH HOEGH.exe Client3 1
  21. HOEGH HOEGH.exe Client4 2
  22. HOEGH HOEGH.exe CLIENT5 28
  23. HOEGH HOEGH.exe Client6 1
  24. HOEGH HOEGH.exe 128
  25. HOEGH 128
  26.                                                             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报错。

点击(此处)折叠或打开

  1. 10-6月 -2015 16:26:53 * service_update * hoegh * 0
  2. 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 * 12514
  3. TNS-12514: TNS: 监听程序当前无法识别连接描述符中请求的服务
  4. 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 * 12514
  5. TNS-12514: TNS: 监听程序当前无法识别连接描述符中请求的服务
  6. 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 * 12514
  7. TNS-12514: TNS: 监听程序当前无法识别连接描述符中请求的服务
  8. 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 * 12514
  9. TNS-12514: TNS: 监听程序当前无法识别连接描述符中请求的服务
  10. 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 * 12514
  11. TNS-12514: TNS: 监听程序当前无法识别连接描述符中请求的服务
  12. 10-6月 -2015 16:27:08 * service_update * hoegh * 0
  13. 10-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中添加了静态监听,其中黄色部分为新添加内容。
但是,效果不大。

点击(此处)折叠或打开

  1. SID_LIST_LISTENER =
  2.   (SID_LIST =
  3.     (SID_DESC =
  4.       (SID_NAME = PLSExtProc)
  5.       (ORACLE_HOME = c:\\oracle\\product\\10.2.0\\db_1)
  6.       (PROGRAM = extproc)
  7.     )
  8.     (SID_DESC =
  9.       (SID_NAME = hoegh)
  10.       (ORACLE_HOME = c:\\oracle\\product\\10.2.0\\db_1)
  11.     )
  12.   )

  13. LISTENER =
  14.   (DESCRIPTION_LIST =
  15.     (DESCRIPTION =
  16.       (ADDRESS = (PROTOCOL = TCP)(HOST = DBSERVER)(PORT = 1521))
  17.       (ADDRESS = (PROTOCOL = IPC)(KEY = EXTPROC0))
  18.     )
  19.   )

增大processes初始化参数

黔驴技穷,我又使了这招,可是丝毫不起作用,不同的是以往连接总数是一百三四十,现在增加到了二百七八十,问题依旧。
结合上面的静态监听,我再次查看listener.log,发现大量TNS-12518和TNS-12560报错,以及少量的TNS-12514报错:

点击(此处)折叠或打开

  1. 15-6月 -2015 15:39:13 * 12502
  2. TNS-12502: TNS: 监听程序没有从客户机收到 CONNECT_DATA
  3. 15-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 * 12518
  4. TNS-12518: TNS: 监听程序无法分发客户机连接
  5.  TNS-12560: TNS: 协议适配器错误
  6. 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 * 12518
  7. TNS-12518: TNS: 监听程序无法分发客户机连接
  8.  TNS-12560: TNS: 协议适配器错误
  9. 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 * 12518
  10. TNS-12518: TNS: 监听程序无法分发客户机连接
  11.  TNS-12560: TNS: 协议适配器错误
  12. 15-6月 -2015 15:39:13 * 12502
  13. TNS-12502: TNS: 监听程序没有从客户机收到 CONNECT_DATA
  14. 15-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 * 12518
  15. TNS-12518: TNS: 监听程序无法分发客户机连接
  16.  TNS-12560: TNS: 协议适配器错误
  17. 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 * 12518
  18. TNS-12518: TNS: 监听程序无法分发客户机连接
  19.  TNS-12560: TNS: 协议适配器错误
  20. 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 * 12518
  21. TNS-12518: TNS: 监听程序无法分发客户机连接
  22.  TNS-12560: TNS: 协议适配器错误

重建监听器

重启设备是一个“大招”,以前碰到“疑难杂症”重启往往能够收到奇效。最后,我甚至都想着重建数据库了,不过考虑着动静有点大,可能会影响其他人工作,只好作罢;那我重建一下监听试一下吧。

于是,我通过netca删除原有监听,重建监听程序listener,都采用默认配置。

可是,问题依旧。

更换微软驱动System.Data.OracleClient

真是没招了,最后和部门的架构师一起讨论这个问题,会不会和数据库驱动有关系呢。
我们的应用程序是用C#开发的,连接数据库需要数据驱动支持,以前我们采用的是微软的数据库驱动System.Data.OracleClient,最近这个项目换成了Oracle官方驱动Oracle.ManagedDataAccess.Client。至于为什么要换,最主要是考虑Oracle官方驱动部署方便,无需安装Oracle数据库客户端。

说干就干,把实验室的所有客户端设备的驱动都更换为System.Data.OracleClient,我再去查看session连接状况,看到输出结果哭了都快,session数真的好少啊!!!

点击(此处)折叠或打开

  1. SQL> set pagesize 150
  2. SQL> set linesize 200
  3. SQL> col username for a10
  4. SQL> col terminal for a20
  5. SQL> col program for a20
  6. SQL> select username,program,terminal,count(*) from v$session group by rollup(username,program,terminal);
  7.  
  8. USERNAME PROGRAM TERMINAL COUNT(*)
  9. ---------- -------------------- -------------------- ----------
  10. ......此处省略内容
  11.            ORACLE.EXE (q000) 1
  12.            ORACLE.EXE (q001) DBSERVER 1
  13.            ORACLE.EXE (q001) 1
  14.                                                              16
  15. SYS sqlplus.exe DBSERVER 1
  16. SYS sqlplus.exe 1
  17. SYS 1
  18. HOEGH HOEGH.exe Client7 1
  19. HOEGH HOEGH.exe CLIENT2 1
  20. HOEGH HOEGH.exe Client3 1
  21. HOEGH HOEGH.exe Client4 2
  22. HOEGH HOEGH.exe CLIENT5 1
  23. HOEGH HOEGH.exe Client6 1
  24. HOEGH HOEGH.exe 7
  25. HOEGH 7
  26.                                                             24


说到最后的话

这个问题折腾一个多月了,现在看似得到彻底解决,但是心里还是不踏实,毕竟Oracle官方驱动Oracle.ManagedDataAccess.Client还是有不少优点的。
  • Oracle驱动部署方便,数据类型兼容性好,如Timestamp类型支持保存ms级数据(大家可以参考以前的一篇博文http://blog.itpub.net/30162081/viewspace-1561171/
  • 微软驱动更加稳定,但是不再提供更新,无法支持一些新特性。

那么,问题来了,会不会是我们的使用方法有问题呢,还请用过Oracle官方驱动Oracle.ManagedDataAccess.Client的朋友不吝赐教。

原来是它(Oracle.ManagedDataAccess.Client)——再说ORA-12516故障解决

原文:http://blog.itpub.net/30162081/viewspace-1703627/

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!