JAVA JDBC连接打开不及时关闭导致Oracle报错ORA-00020&ORA12516
JAVA web项目JDBC连接池配置过大,或者JAVA数据源JDBC连接类编写不规范,打开链接不及时关闭,会导致数据库进
程数超过最大值而拒绝新连接。最近,一客户的遇到的问题就是典型的JDBC连接类打开会话不关闭导致应用链接报错:ORA-00020&ORA12516。
一、问题描述
JAVA WEB应用前台报错数据库连接超时,web中间件后台报错ORA-12516,报错信息如下:
观察Oracle数据库告警日志,会发现ORA-0020报错:
有趣的是:因为数据库是新安装部署的,开发同事并不认为这是应用导致的。作为运维的人,只能自己写个JAVA JDBC类,
重启数据库,通过自己的JAVA JDBC类操作数据库,一切如常。
JDBC JAVA类:
package com.cn;
import java.sql.*;
public class JDBCTest {
// dbUrl数据库连接串信息,其中“1521”为端口,“ora9”为sid
String dbUrl = "jdbc:oracle:thin://@117.113.168.198:1521/DB";
// theUser为数据库用户名
String theUser = "assure";
// thePw为数据库密码
String thePw = "assure";
// 几个数据库变量
Connection c = null;
Statement conn;
ResultSet rs = null;
// 初始化连接
public JDBCTest() {
try {
Class.forName("oracle.jdbc.driver.OracleDriver").newInstance();
// 与url指定的数据源建立连接
c = DriverManager.getConnection(dbUrl, theUser, thePw);
// 采用Statement进行查询
conn = c.createStatement();
} catch (Exception e) {
e.printStackTrace();
}
}
// 执行查询
public ResultSet executeQuery(String sql) {
rs = null;
try {
rs = conn.executeQuery(sql);
} catch (SQLException e) {
e.printStackTrace();
}
return rs;
}
public void close() {
try {
conn.close();
c.close();
} catch (Exception e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
System.out.println("Test is true!");
ResultSet newrs;
JDBCTest newjdbc = new JDBCTest();
System.out.println(newjdbc);
newrs = newjdbc.executeQuery("select * from dba_users");
try {
while (newrs.next()) {
System.out.print(newrs.getString("USER_ID"));
System.out.print("\t" + newrs.getString("USERNAME"));
System.out.println("\t"+newrs.getString("DEFAULT_TABLESPACE"));
}
} catch (Exception e) {
e.printStackTrace();
}
newjdbc.close();
}
}
操作结果如下:
在后续的问题追踪中,也发现WEB应用一启动就占用数据库470个会话连接:
为了说明非数据库配置问题将数据库进程数调整到3000,会话连接数调整到4500:
但是,应用程序启动后,还是会报数据库连接异常,到这里问题基本确定,导致应用链接数据库异常的原因是超过数据库
最大进程数,数据库不能无限制的提供资源,最佳的解决方法是应用程序自身从根本上杜绝。