由JDBC引起的故障多数与连接池配置有关,主要可以分为下面几类:
(1)WLS启动缓慢;
(2)连接池创建缓慢或失败;
(3)WLS运行过程出现问题,比如ResourceException、NO resources available、SQL Exception、OutOfMemoryError等;
(4)WLS在运行过程中崩溃,WLS服务器或应用程序挂起;
(5)服务器出现故障后不能重新建立连接;
(6)JDBC不当配置导致DB出现问题,比如打开的游标过多等;
(7)内存泄露;
(8)防火墙问题,比如关闭空闲连接、空闲JMS连接问题。
由创建连接池造成的WLS启动缓慢
问题描述及成因
WLS在启动时,会创建连接池和建立JDBC连接,因此如果建立JDBC连接时花费的时间比较多的话,WLS的启动就会很缓慢。
解决办法
(1)减小InitialCapacity值,创建的连接少了,初始化连接池所需要的时间也就少了;使用CapacityIncrement值以确保单个请求,可以触发多个连接的创建;
(2)将InitialCapacity设置为0,强CapacityIncrement设置为MaxCapacity,这样会在第一个连接请求创建所有需要的连接,代价是第一个连接请求会花费很长的时间,好处是在这时候,整个连接池就可以正常的工作了;
注意:某些JDBC驱动器,比如Oracle 4类驱动器,在8.1 SP2期之后版本中使用时,可以限制连接请求的最大等待时间,对于这些驱动程序,可以在config.xml配置文件里配置JDBCConnectionPool时设置LoginTimeout参数,这个参数会由WebLogic Server传递给JDBC驱动。
连接池创建失败
问题描述及成因
WebLogic Server在启动时,会创建特定数量的、到数据库的物理连接,具体的数量由InitialCapacity参数来定。此时如果JDBC的连接配置的不正确或者数据库不可用,物理连接的初始化就会失败,连接池的创建就会失败。
如果WLS启动时数据库不可用的话,WebLogic会如何处理?
(1)对于WLS 8.1之前的版本,将不会创建JDBC连接池,因此也就无法使用JDBC连接池;
(2)对于WLS 8.1和更高的版本,将先创建一个大小为0的连接池(默认情况),如果过后DB变为可用,将在请求时创建连接,否则将继续报错。
解决办法
(1)对于WLS 8.1之前的版本,配置一个在启动时不会打开任何连接的连接池,也就是将InitialCapacity参数设置为0。这样能成功创建连接池。之后对于每个连接请求,连接池会更具CapacityIncrement参数指定的个数创建连接,当然,如果数据库仍然不可用,就会报错。
(2)从8.1的版本开始,在创建连接池时遇到问题的话,默认就会创建一个0初始连接的连接池,然后等连接池配置正确或者数据库可用以后再创建连接,以供后续的应用程序使用。WebLogic的数据库连接池中有一个参数Connection Creation Retry Frequency与该属性有关,此参数表示重新创建数据库连接的间隔时间(以秒为单位),如果设置为0,表示不会重连数据库。
JDBC配置不正确造成的连接池创建问题
ORA-12405错误:监听器无法识别连接描述符中指定的SID
问题描述
ORA-12405,TNS:listener does not currently know of SID given in connection descriptor
Oracle监听器无法识别客户端发送过来的连接描述符。
解决思路
检查tnsnames.ora文件中网络协议、IP、端口、SID或SERVICE_NAME等参数配置得是否正确。
ORA-01017错误:无效的用户名密码
问题描述
ORA-01017: invalid username/password;logon denied
解决思路
检查设置的用户名和密码是否正确。
网络适配器无法建立连接错误
问题描述
The Network Adapter could not establish the connection
如果tnsnames.ora文件或者环境变量$PATH或$LD_LIBRARY_PATH配置得不正确的话,就可能会遇到网络适配器无法连接错误。
解决思路
(1)检查tnsnames.ora文件中网络协议、IP、端口、SID或SERVICE_NAME等参数配置得是否正确。
(2)$PATH应该包含$ORACLE_HOME/bin目录;$LD_LIBRARY_PATH应该包含$ORACLE_HOME/lib和OCI库目录。
ORA-12054:服务名错误
问题描述
ORA-12054: TNS could not resolve service name
如果tnsnames.ora文件或者环境变量$ORACLE_HOME配置不正确的话,就有可能出现此错误。
解决思路
(1)检查环境变量$ORACLE_HOME的设置是否正确,应该为Oracle软件安装的根目录。
(2)检查tnsnames.ora文件中网络协议、IP、端口、SID或SERVICE_NAME等参数配置得是否正确。
(3)通过sqlplus等工具检测一下,看看是否能通过其他工具登录Oracle数据库,如果可以正常登录,那很可能就是配置问题;如果不能正常登录,那么很可能是数据库的问题,此时需要对数据库做检查。
ORA-23326:用户认证错误
问题描述
ORA-23326:need explicit attach before authenticating a user
如果tnsnames.ora文件或者环境变量$PATH或$LD_LIBRARY_PATH配置得不正确的话,就可能出现此类问题。
解决思路
(1)tnsnames.ora文件,对于2类驱动程序,需要检查ORACLE_SID、SERVICE_NAME和数据库服务器主机字符串值是否正确,并确保一下文件中的连接池属性配置正确:config.xml weblogic.properties。
(2)检查$PATH应该包含$ORACLE_HOME/bin目录;$LD_LIBRARY_PATH应该包含$ORACLE_HOME/lib和OCI库目录。
(3)通过sqlplus等工具检测一下,看看是否能通过其他工具登录Oracle数据库,如果可以正常登录,那很可能就是配置问题;如果不能正常登录,那么很可能是数据库的问题,此时需要对数据库做检查。
unable to load locale category
问题描述
如果本地环境变量设置不正确的话,可能会遇到次错误。
解决思路
很可能是本地环境变量设置的问题,此时需要检查本地环境变量。另外尝试在相同的环境下启动数据库客户端,看看是否能够正常启动,并检查环境变量的设置是否能正常起作用。
资源异常问题
资源异常概述
问题描述
应用程序请求连接(也就是调用getConnection())时,可能遇到ResourceException资源异常错误。
问题原因
连接池中没有可用的连接;
没有线程可用于处理连接请求,因为JDBC连接使用服务器线程来执行工作,没有了线程,自然就不能正常处理连接请求了。
总体排查思路
连接池中是否有足够的连接来应对暂时性的连接高峰;
是否有足够的连接可用于所需数量的并发客户端JDBC会话;
是否存在连接泄露问题;
是否启用了自动连接测试;
同时保留和测试的连接是否过多;
连接测试是否太过频繁;
是否有足够的线程可用于JDBC工作。
连接数不足造成的资源异常
由于连接数确实不能满足要求造成的资源异常
比如暂时性的连接高峰,或者所需的并发JDBC会话数量增多;
连接池中连接数受限于MaxCapacity所设置的最大值;默认值为默认的执行线程数,对于开发模式默认为15,对于生产模式默认为24.
所需池的大小,实际池的大小能会更大,但适当设置MaxCapacity可以将并行DB访问控制在DB、网络、CPU等容量限制之内。
连接泄露造成的可用连接数过少
首先声明是连接泄露?
应用程序在适用完连接后,应该调用close()关闭该连接(即释放该连接),将连接返还到连接池,以便该连接可供其他应用程序使用,如果应用程序没有释放连接,从而导致该连接不能被其他应用程序使用,这种现象就是连接泄露。如果有太多的连接处于泄露状态的话,那么连接池中的可用连接数将会越来越少,这样最终很可能导致出现ResourceException资源异常错误。
解决方法
对于连接泄露,WLS提供了一种检测连接泄露的功能,可以再config.xml文件中将ConnLeakProfilingEnable设置为true。也可以再admin console里进行设置。在开启检测功能以后,在从连接池里分配了连接对象并将其赋给某个客户端以后,连接池就会开始保存堆栈跟踪信息,当发现出现连接泄露时,就会报告相关的堆栈跟踪信息。连接池如果判断连接泄露?当发现之前分配的连接对象,被当做垃圾回收了,就判定该连接出现了连接泄露。另外,可以对产生的堆栈跟踪进行分析以辅助查找泄露的具体原因。
注意:连接泄露探测功能会占用额外的资源,很可能降低连接池的性能,所以不建议在生产环境中使用此方法。
对于Oracle数据库,出现连接泄露以后,很可能会遇到:
自动连接测试造成的可用连接数过少
问题成因
在进行连接测试时,不管是手动还是自动都会将连接处于一种reserved的状态,在测试期间连接不能被应用程序使用。此时,如果设置了自动测试,那么在某一时刻就可能会出现:有太多的连接处于reserved状态,连接池里没有空闲连接。如果此时又有应用程序申请连接,那么就会报ResourceException错误。
如果在排查时,通过分析应用程序,发现连接池里保留的连接数要比应用程序使用的连接数多,并且已经排除了连接泄露的可能,那么很可能是因为自动测试造成的连接数不够的问题。
解决方法
将时间间隔设置的小一些,设置Test-Frequency-Seconds/Refresh-Minutes参数。
考虑禁用自动连接测试,默认就是禁用的。
ORA-01000 打开的游标数过多错误
问题描述
ORA-00604: error occurred at recursive SQL level 1
ORA-01000: maximum open cursors exceeded
如上错误表示会话打开的游标已经达到数据库允许单个会话同时打开的游标的上限。
什么对象使用游标?prepared statement对象;其他对象,如存储过程或结果集。
注意:虽然prepared statement使用一个打开的游标,但是考虑到每个连接会缓存statementCacheSize个prepared statement,而连接池里最多又可能有MaxCapacity个连接,那么最终就会打开MaxCapacity * StatementCacheSize 个游标。也就是说,prepared statement对象可能会需要MaxCapacity*StatementCacheSize个游标。
解决方法
(1)检查数据库是否配置了足够多的游标来满足所有池及其他对象的要求。每个池所需要的游标值为MaxCapacity*StatementCacheSize+备用游标。Oracle数据库中,控制每个会话可以一次打开的游标个数的参数时open_cursors。
(2)更改数据库的限制,增大允许打开的游标的上限。因为也确实存在游标不够用的问题。如果是Oracle数据库的话,可以 alter system set open_cursors=n scope=both。
(3)Oracle的某些驱动存在游标泄露问题。某些版本的Oracle驱动(thin或oci)在XA驱动类(oracle.jdbc.xa.client.OracleXA-DataSource)中存在游标泄露问题,所以在一定时间过后,就可能造成打开游标过多的错误。此时需要确保在数据库中,DBA_PENDING_TRANSACTION视图有正确的权限。
注意:游标泄露问题,在Oracle数据库9.2.0.5及以后版本中得到了解决。
ORA-03113 连接中断错误或 01012未登录错误
ORA-03113: end-of-file on communication channel
问题描述
如果数据库出现了间歇性故障,并且又将TestConnectionsOnReserve参数设置为true(在连接交给应用程序之前先测试属性),那些在数据库故障期间出现异常的连接就会被刷新,此时在WebLogic的日志文件里,就会有相应的记录。
解决方法
对于数据库间歇性故障,为确保连接至可以从DB失败中恢复,可以启用连接自动测试和重建。
防火墙关闭空闲连接问题
问题描述
如果在WLS和数据库之间使用了防火墙的话,在连接空闲一定长时间后,还没有被使用的话,防火墙就可能会关闭这些连接。但是,对于这些连接,WLS和数据库却都认为是好的,是可用的,所以就会去尝试写这些Socket连接,连接又已经被关闭,此时就会报错。
ORA-03113: end-of-file on communication channel
解决方法
使用连接池的自动测试或者刷新功能,设置下面两个参数之一,确保在防火墙超时期间内每个连接至少被激活一次。
RefreshMinutes(8.X之前的版本使用)
TestFrequencySeconds(8.X及之后的版本使用)
防火墙关闭空闲JMS连接问题
问题描述
如果JMS采用JDBC持久性存储,每个JMS服务器会使用JDBC连接池中的一个连接,由于该连接时保留连接,因此不会被视为空闲连接,该JMS连接也就不会得到定期测试,因此,如果JMS连接长期空闲的话,防火墙就可能会关闭该JMS服务器连接。
JMSServer "myJMSServer",store failure while writing message for queue myQueue,java.io.IOException
解决方法
在防火墙超时期间内至少发送一个伪消息
禁用防火墙的关闭连接功能
定义一个单独的JMS服务器JDBC池,并使用weblogic.Admin RESET_POOL命令,在每个超时期间内至少再打开一次连接
使用WLS 6.1 SP7或者更高版本,这些版本会每5分钟对空闲JMS连接执行一次ping命令,以防止防火墙关闭连接。
WebLogic Server 崩溃
问题描述
2类JDBC驱动程序可以将JDBC(java)方法调用转换为本地数据库API调用,而本地调用的问题可能会造成JVM和WLS崩溃。
另外,JDBC连接使用WebLogic Server执行线程来执行它的工作。如果出现下列问题,服务器线程可能会挂起,例如,需要重建大量连接。或者数据库基础结构问题或死锁也会导致请求挂起,其结果可能是应用程序挂起或者整个服务器挂起。
解决方法
(1)改为使用纯java(4类)JDBC驱动程序。
(2)进行记录和调试可能会确定故障发生的原因。