我有一個Java EE應用程序在Glassfish運行,並通過JTDS連接MSSQL Server 2008的關閉。由於某些未知原因,數據庫連接在請求期間意外關閉。該應用程序是巨大的,但這裏是錯誤發生的概要:數據庫連接意外與Glassfish的,JTDS和SQL Server 2008
在Glassfish安裝過程中,創建一個連接池asadmin create-jdbc-connection-pool
和asadmin create-jdbc-resource
。數據源類是net.sourceforge.jtds.jdbcx.JtdsDataSource
。
當Glassfish的上升,它要求我們實施ServletContextListener.contextInitialized的(),我們取從JNDI數據源。數據源存儲在一個靜態變量中。
有一段時間,一切都很好。所有請求都被處理並且沒有連接被關閉。我們的應用程序使用Timer和MDB(消息驅動Bean)EJB來執行處理。
這是一個示例onMessage()
實現:
public void onMessage(Message message) {
this.message = message;
this.connection = dataSource.getConnection(userName, password);
try {
doQuery1();
doTransaction1();
doTransaction2();
doQuery2();
doQuery3();
} finally {
this.connection.close();
this.connection = null;
}
}
最後,我們開始出現以下情況例外(發生在一小時內約100次):
java.sql.SQLException: Invalid state, the Connection object is closed.
at net.sourceforge.jtds.jdbc.ConnectionJDBC2.checkOpen(ConnectionJDBC2.java)
at net.sourceforge.jtds.jdbc.ConnectionJDBC2.prepareStatement(ConnectionJDBC2.java)
at net.sourceforge.jtds.jdbc.ConnectionJDBC2.prepareStatement(ConnectionJDBC2.java)
at com.sun.gjc.spi.base.ConnectionHolder.prepareStatement(ConnectionHolder.java:475)
at com.acme.myejbs.MyMDB.doQuery2(MyMDB.java:123)
at com.acme.myejbs.MyMDB.onMessage(MyMDB.java:614)
at sun.reflect.GeneratedMethodAccessor115.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java)
at java.lang.reflect.Method.invoke(Method.java)
at com.sun.enterprise.security.application.EJBSecurityManager.runMethod(EJBSecurityManager.java:1011)
...
at $Proxy92.onMessage(Unknown Source)
at com.sun.messaging.jms.ra.OnMessageRunner.run(OnMessageRunner.java)
at com.sun.enterprise.connectors.work.OneWork.doWork(OneWork.java:77)
at com.sun.corba.ee.impl.orbutil.threadpool.ThreadPoolImpl$WorkerThread.run(ThreadPoolImpl.java:555)
唯一的例外發生在隨機JDBC調用。有時候是在ResultSet迭代期間,在查詢執行期間的其他時間。 (一小時內5次)
java.sql.SQLException: Error in allocating a connection. Cause: This Managed Connection is not valid as the phyiscal connection is not usable
at com.sun.gjc.spi.base.DataSource.getConnection(DataSource.java:136)
at com.acme.myejbs.MyMDB.onMessage(MyMDB.java:614)
at sun.reflect.GeneratedMethodAccessor115.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java)
at java.lang.reflect.Method.invoke(Method.java)
at com.sun.enterprise.security.application.EJBSecurityManager.runMethod(EJBSecurityManager.java:1011)
...
at $Proxy92.onMessage(Unknown Source)
at com.sun.messaging.jms.ra.OnMessageRunner.run(OnMessageRunner.java)
at com.sun.enterprise.connectors.work.OneWork.doWork(OneWork.java:77)
at com.sun.corba.ee.impl.orbutil.threadpool.ThreadPoolImpl$WorkerThread.run(ThreadPoolImpl.java:555)
此外,在極少數情況下,我們得到這個異常:
在極少數情況下(一小時內7次),我們得到這個異常
java.sql.SQLException: I/O Error: Connection reset by peer: socket write error
at net.sourceforge.jtds.jdbc.TdsCore.executeSQL(TdsCore.java)
at net.sourceforge.jtds.jdbc.JtdsStatement.executeSQLQuery(JtdsStatement.java)
at net.sourceforge.jtds.jdbc.JtdsPreparedStatement.executeQuery(JtdsPreparedStatement.java)
at com.acme.myejbs.MyMDB.doQuery2(MyMDB.java:126)
at com.acme.myejbs.MyMDB.onMessage(MyMDB.java:614)
...
Caused by: java.net.SocketException: Connection reset by peer: socket write error
at java.net.SocketOutputStream.socketWrite0(Native Method)
at java.net.SocketOutputStream.socketWrite(SocketOutputStream.java)
at java.net.SocketOutputStream.write(SocketOutputStream.java)
at java.io.DataOutputStream.write(DataOutputStream.java)
at net.sourceforge.jtds.jdbc.SharedSocket.sendNetPacket(SharedSocket.java)
at net.sourceforge.jtds.jdbc.RequestStream.putPacket(RequestStream.java)
at net.sourceforge.jtds.jdbc.RequestStream.flush(RequestStream.java)
... 44 more
在極少數情況下,我們得到這個可怕的例外(內JTDS NPE):
java.lang.NullPointerException
at net.sourceforge.jtds.jdbc.JtdsPreparedStatement.executeQuery(JtdsPreparedStatement.java)
at com.acme.myejbs.MyMDB.doQuery2(MyMDB.java:126)
at com.acme.myejbs.MyMDB.onMessage(MyMDB.java:614)
...
我們找不到爲什麼會這樣。請求期間使用的連接永遠不會空閒超過一秒鐘。我們不知道誰在斷開連接。這可能是網絡不穩定,但是我認爲jTDS應該只產生與網絡相關的異常,對吧?
另一種選擇是Glassfish的連接池的一些策略或配置(也許GlassFish是過早地關閉物理連接),但我們怎麼可以跟蹤它?
最後,MS SQL Server 2008的可以遠程連接下探,但我們怎麼可以監視服務器端知道它是怎麼回事?
不要的問題也發生使用微軟的JDBC驅動程序時? – extraneon
@extraneon我們沒有測試Microsoft JDBC驅動程序。有一個基於jTDS的整個持久層,切換到MS需要幾天時間才能完成。 – fernacolo
您的代碼是捕捉/忽略SQLExceptions嗎?你使用的是基本的數據源還是連接池? –