我们有一个带有Web UI和REST API的多线程java应用程序,它使用java 6编译并在tomcat 6中运行。在操作期间,它使用OJDBC每天访问其Oracle DB数百万次。每隔两三个月,一个数据库查询会挂起并且永不返回,这会导致部分应用程序停止处理并创建积压工作。其他线程能够与数据库进行通信并完成工作,只有一个线程被挂起,不幸的是,这会停止文件处理。
线程转储显示线程正在从一个永不超时或关闭的套接字读取:
"FileUpload" daemon prio=10 tid=0x00002b8e60617800 nid=0xf9e runnable [0x00002b8e5e10b000]
java.lang.Thread.State: RUNNABLE
at java.net.SocketInputStream.socketRead0(Native Method)
at java.net.SocketInputStream.read(SocketInputStream.java:129)
at oracle.net.ns.Packet.receive(Packet.java:311)
at oracle.net.ns.DataPacket.receive(DataPacket.java:103)
at oracle.net.ns.NetInputStream.getNextPacket(NetInputStream.java:312)
at oracle.net.ns.NetInputStream.read(NetInputStream.java:257)
at oracle.net.ns.NetInputStream.read(NetInputStream.java:182)
at oracle.net.ns.NetInputStream.read(NetInputStream.java:99)
at oracle.jdbc.driver.T4CSocketInputStreamWrapper.readNextPacket(T4CSocketInputStreamWrapper.java:121)
at oracle.jdbc.driver.T4CSocketInputStreamWrapper.read(T4CSocketInputStreamWrapper.java:77)
at oracle.jdbc.driver.T4CMAREngine.unmarshalUB1(T4CMAREngine.java:1173)
at oracle.jdbc.driver.T4CTTIfun.receive(T4CTTIfun.java:309)
at oracle.jdbc.driver.T4CTTIfun.doRPC(T4CTTIfun.java:200)
at oracle.jdbc.driver.T4C8Oall.doOALL(T4C8Oall.java:543)
at oracle.jdbc.driver.T4CPreparedStatement.doOall8(T4CPreparedStatement.java:238)
at oracle.jdbc.driver.T4CPreparedStatement.executeForDescribe(T4CPreparedStatement.java:1244)
at oracle.jdbc.driver.OracleStatement.executeMaybeDescribe(OracleStatement.java:1492)
at oracle.jdbc.driver.OracleStatement.doExecuteWithTimeout(OracleStatement.java:1710)
at oracle.jdbc.driver.OraclePreparedStatement.executeInternal(OraclePreparedStatement.java:4372)
at oracle.jdbc.driver.OraclePreparedStatement.executeQuery(OraclePreparedStatement.java:4453)
- locked <0x00002b8e1c2d7010> (a oracle.jdbc.driver.T4CConnection)
at oracle.jdbc.driver.OraclePreparedStatementWrapper.executeQuery(OraclePreparedStatementWrapper.java:6270)
at org.apache.tomcat.dbcp.dbcp.DelegatingPreparedStatement.executeQuery(DelegatingPreparedStatement.java:96)
at org.apache.tomcat.dbcp.dbcp.DelegatingPreparedStatement.executeQuery(DelegatingPreparedStatement.java:96)
at xxx.OracleFileInfoDAO.getFilesToUpload(OracleFileInfoDAO.java:874)
当发生这种情况时,DBA会查看数据库服务器,并且看不到长时间运行的查询。解决方案是回收tomcat来解决问题,但我想知道是否有一种编程方式来处理这个问题。我看到附加内容指的是通过回收运行数据库服务器的LINUX盒解决的类似问题,但这对我们来说不是一个选择;我需要在应用程序级别修复。
使用以下命令定义DB资源:
<Resource auth="Container" description="Oracle Datasource" name="xxx" scope="shareable" type="javax.sql.DataSource" url="jdbc:oracle:thin:@xxx:1521/xxx" driverClassName="oracle.jdbc.driver.OracleDriver" username="xxx" password="xxx" maxWait="5000" maxActive="100" maxIdle="20" removeAbandoned="true" testOnReturn="true" testOnBorrow="true" validationQuery="select 1 from dual" />
使用的OJDBC驱动程序是:ojdbc6_g-11.2.0.4.0.jar
数据库版本为:11.2.0.3.0
执行查询的java代码是:
con = CSAConnectionManager.getConnection();
StringBuilder strBuf = new StringBuilder(SQL_SELECT_FILE_INFO_TO_UPLOAD);
ps = con.prepareStatement(strBuf.toString());
ps.setString( 1, hostname );
ps.setString( 2, containerId );
ps.setMaxRows( maxRows );
Date before = new Date();
ResultSet rs = ps.executeQuery();
这是getConnection()的来源:
public static Connection getConnection() throws Exception
{
return instance.getInstanceConnection();
}
public Connection getInstanceConnection() throws Exception
{
Connection con = null;
if(ds != null)
{
con = ds.getConnection();
}
else
{
String dburl = wrapper.getDBUrl();
String username = wrapper.getDBUserName();
String password = wrapper.getDBPassword();
String driverClass = wrapper.getDBDriverClass();
Class.forName(driverClass).newInstance();
con = DriverManager.getConnection(dburl,username,password);
}
con.setAutoCommit(false);
return con;
}
“ds”定义为:private static DataSource ds = null; 并使用以下方式初始化:
Context initContext = new InitialContext();
ds = (DataSource)initContext.lookup(wrapper.getCSADBJNDIName());
答案 0 :(得分:1)
根据我的经验,这通常是网络错误。您的查询已完成,但您的客户端仍在阻止它永远不会收到的网络响应。这就是为什么弹跳应用服务器的工作方式,因为它重置应用服务器中的所有内容,但弹跳数据库服务器是没有意义的,因为它不是数据库问题。在这个网站上看看这个问题/答案......
答案 1 :(得分:1)
检查会话是否:
同时检查连接风暴(即访问实例的会话太多会导致严重的CPU问题)