jdbc14 及 jdbc16 共存所帶來的問題【未完待續】

在JAVA中JDK版本與JDBC版本的一致性十分重要,開發都們常常會忽略了這一點導致很多不必要的錯誤。昨天給客戶排查了一個關於EDB在JBoss中使用時關於這方面的問題,希望給大家一點啓發。


系統環境:

Red Hat Enterpirse Linux 6

JBoss Enterprise Application Server 6

EnterpriseDB Postgres Plus Advanced Server 9

Oracle JDK 1.6


問題症狀:

在JBoss日誌中間歇性地出現以下錯誤

java.sql.SQLException: javax.resource.ResourceException: IJ000453: Unable to get managed connection for java:/jdbc/DSZY101----Caused by: javax.resource.ResourceException: IJ000453: Unable to get managed connection for java:/jdbc/DSZY101--       at org.jboss.jca.core.connectionmanager.AbstractConnectionManager.getManagedConnection(AbstractConnectionManager.java:390)--         at org.jboss.jca.core.connectionmanager.tx.TxConnectionManagerImpl.getManagedConnection(TxConnectionManagerImpl.java:368)--         at org.jboss.jca.core.connectionmanager.AbstractConnectionManager.allocateConnection(AbstractConnectionManager.java:464)--         at org.jboss.jca.adapters.jdbc.WrapperDataSource.getConnection(WrapperDataSource.java:159)--         at jp.co.toyota.perz060.servlet.CCERZ060.getConnection(CCERZ060.java:489)--   at jp.co.toyota.perz060.servlet.CCERZ060.doPost(CCERZ060.java:118)--         at javax.servlet.http.HttpServlet.service(HttpServlet.java:754)--      at javax.servlet.http.HttpServlet.service(HttpServlet.java:847)-- at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:329)--  at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:248)--        at jp.co.toyota.pzy1352.util.CIZY1392.doFilter(CIZY1392.java:362)--        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:280)--  at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:248)--        at jp.co.toyota.pzy1900.util.CIZY1947.doFilter(CIZY1947.java:99)-- at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:280)--  at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:248)--        at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:275)--     at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:161)--        at org.jboss.as.web.security.SecurityContextAssociationValve.invoke(SecurityContextAssociationValve.java:153)--     at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:155)-- at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102)--     at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)--   at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:368)--     at org.apache.coyote.ajp.AjpProcessor.process(AjpProcessor.java:505)--        at org.apache.coyote.ajp.AjpProtocol$AjpConnectionHandler.process(AjpProtocol.java:452)--       at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:931)--      at java.lang.Thread.run(Thread.java:662)----Caused by: javax.resource.ResourceException: IJ000658: Unexpected throwable while trying to create a connection: null--          at org.jboss.jca.core.connectionmanager.pool.mcp.SemaphoreArrayListManagedConnectionPool.getConnection(SemaphoreArrayListManagedConnectionPool.java:371)--         at org.jboss.jca.core.connectionmanager.pool.AbstractPool.getSimpleConnection(AbstractPool.java:397)--    at org.jboss.jca.core.connectionmanager.pool.AbstractPool.getConnection(AbstractPool.java:365)--   at org.jboss.jca.core.connectionmanager.AbstractConnectionManager.getManagedConnection(AbstractConnectionManager.java:329)--         at org.jboss.jca.core.connectionmanager.tx.TxConnectionManagerImpl.getManagedConnection(TxConnectionManagerImpl.java:368)--         at org.jboss.jca.core.connectionmanager.AbstractConnectionManager.allocateConnection(AbstractConnectionManager.java:464)--         at org.jboss.jca.adapters.jdbc.WrapperDataSource.getConnection(WrapperDataSource.java:159)--         at jp.co.toyota.perz060.servlet.CCERZ060.getConnection(CCERZ060.java:489)--   at jp.co.toyota.perz060.servlet.CCERZ060.doPost(CCERZ060.java:118)--         at javax.servlet.http.HttpServlet.service(HttpServlet.java:754)--      at javax.servlet.http.HttpServlet.service(HttpServlet.java:847)-- at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:329)--  at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:248)--        at jp.co.toyota.pzy1352.util.CIZY1392.doFilter(CIZY1392.java:362)--        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:280)--  at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:248)--        at jp.co.toyota.pzy1900.util.CIZY1947.doFilter(CIZY1947.java:99)-- at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:280)--  at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:248)--        at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:275)--     at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:161)--        at org.jboss.as.web.security.SecurityContextAssociationValve.invoke(SecurityContextAssociationValve.java:153)--     at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:155)-- at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102)--     at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)--   at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:368)--     at org.apache.coyote.ajp.AjpProcessor.process(AjpProcessor.java:505)--        at org.apache.coyote.ajp.AjpProtocol$AjpConnectionHandler.process(AjpProtocol.java:452)--       at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:931)--      at java.lang.Thread.run(Thread.java:662)----Caused by: javax.resource.ResourceException: Could not create connection-- at org.jboss.jca.adapters.jdbc.local.LocalManagedConnectionFactory.getLocalManagedConnection(LocalManagedConnectionFactory.java:277)--         at org.jboss.jca.adapters.jdbc.local.LocalManagedConnectionFactory.createManagedConnection(LocalManagedConnectionFactory.java:235)--         at org.jboss.jca.core.connectionmanager.pool.mcp.SemaphoreArrayListManagedConnectionPool.createConnectionEventListener(SemaphoreArrayListManagedConnectionPool.java:761)--         at org.jboss.jca.core.connectionmanager.pool.mcp.SemaphoreArrayListManagedConnectionPool.getConnection(SemaphoreArrayListManagedConnectionPool.java:343)--         at org.jboss.jca.core.connectionmanager.pool.AbstractPool.getSimpleConnection(AbstractPool.java:397)--    at org.jboss.jca.core.connectionmanager.pool.AbstractPool.getConnection(AbstractPool.java:365)--   at org.jboss.jca.core.connectionmanager.AbstractConnectionManager.getManagedConnection(AbstractConnectionManager.java:329)--         at org.jboss.jca.core.connectionmanager.tx.TxConnectionManagerImpl.getManagedConnection(TxConnectionManagerImpl.java:368)--         at org.jboss.jca.core.connectionmanager.AbstractConnectionManager.allocateConnection(AbstractConnectionManager.java:464)--         at org.jboss.jca.adapters.jdbc.WrapperDataSource.getConnection(WrapperDataSource.java:159)--         at jp.co.toyota.perz060.servlet.CCERZ060.getConnection(CCERZ060.java:489)--   at jp.co.toyota.perz060.servlet.CCERZ060.doPost(CCERZ060.java:118)--         at javax.servlet.http.HttpServlet.service(HttpServlet.java:754)--      at javax.servlet.http.HttpServlet.service(HttpServlet.java:847)-- at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:329)--  at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:248)--        at jp.co.toyota.pzy1352.util.CIZY1392.doFilter(CIZY1392.java:362)--        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:280)--  at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:248)--        at jp.co.toyota.pzy1900.util.CIZY1947.doFilter(CIZY1947.java:99)-- at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:280)--  at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:248)--        at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:275)--     at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:161)--        at org.jboss.as.web.security.SecurityContextAssociationValve.invoke(SecurityContextAssociationValve.java:153)--     at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:155)-- at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102)--     at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)--   at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:368)--     at org.apache.coyote.ajp.AjpProcessor.process(AjpProcessor.java:505)--        at org.apache.coyote.ajp.AjpProtocol$AjpConnectionHandler.process(AjpProtocol.java:452)--       at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:931)--      at java.lang.Thread.run(Thread.java:662)----Caused by: com.edb.util.PSQLException: The connection attempt failed.--        at com.edb.core.v3.ConnectionFactoryImpl.openConnectionImpl(ConnectionFactoryImpl.java:189)--   at com.edb.core.ConnectionFactory.openConnection(ConnectionFactory.java:64)--        at com.edb.jdbc2.AbstractJdbc2Connection.<init>(AbstractJdbc2Connection.java:161)--        at com.edb.jdbc3.AbstractJdbc3Connection.<init>(AbstractJdbc3Connection.java:30)-- at com.edb.jdbc3g.AbstractJdbc3gConnection.<init>(AbstractJdbc3gConnection.java:23)--   at com.edb.jdbc4.AbstractJdbc4Connection.<init>(AbstractJdbc4Connection.java:31)-- at com.edb.jdbc4.Jdbc4Connection.<init>(Jdbc4Connection.java:25)--     at com.edb.Driver.makeConnection(Driver.java:391)-- at com.edb.Driver.connect(Driver.java:266)--    at org.jboss.jca.adapters.jdbc.local.LocalManagedConnectionFactory.getLocalManagedConnection(LocalManagedConnectionFactory.java:249)--         at org.jboss.jca.adapters.jdbc.local.LocalManagedConnectionFactory.createManagedConnection(LocalManagedConnectionFactory.java:235)--         at org.jboss.jca.core.connectionmanager.pool.mcp.SemaphoreArrayListManagedConnectionPool.createConnectionEventListener(SemaphoreArrayListManagedConnectionPool.java:761)--         at org.jboss.jca.core.connectionmanager.pool.mcp.SemaphoreArrayListManagedConnectionPool.getConnection(SemaphoreArrayListManagedConnectionPool.java:343)--         at org.jboss.jca.core.connectionmanager.pool.AbstractPool.getSimpleConnection(AbstractPool.java:397)--    at org.jboss.jca.core.connectionmanager.pool.AbstractPool.getConnection(AbstractPool.java:365)--   at org.jboss.jca.core.connectionmanager.AbstractConnectionManager.getManagedConnection(AbstractConnectionManager.java:329)--         at org.jboss.jca.core.connectionmanager.tx.TxConnectionManagerImpl.getManagedConnection(TxConnectionManagerImpl.java:368)--         at org.jboss.jca.core.connectionmanager.AbstractConnectionManager.allocateConnection(AbstractConnectionManager.java:464)--         at org.jboss.jca.adapters.jdbc.WrapperDataSource.getConnection(WrapperDataSource.java:159)--         at jp.co.toyota.perz060.servlet.CCERZ060.getConnection(CCERZ060.java:489)--   at jp.co.toyota.perz060.servlet.CCERZ060.doPost(CCERZ060.java:118)--         at javax.servlet.http.HttpServlet.service(HttpServlet.java:754)--      at javax.servlet.http.HttpServlet.service(HttpServlet.java:847)-- at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:329)--  at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:248)--        at jp.co.toyota.pzy1352.util.CIZY1392.doFilter(CIZY1392.java:362)--        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:280)--  at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:248)--        at jp.co.toyota.pzy1900.util.CIZY1947.doFilter(CIZY1947.java:99)-- at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:280)--  at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:248)--        at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:275)--     at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:161)--        at org.jboss.as.web.security.SecurityContextAssociationValve.invoke(SecurityContextAssociationValve.java:153)--     at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:155)-- at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102)--     at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)--   at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:368)--     at org.apache.coyote.ajp.AjpProcessor.process(AjpProcessor.java:505)--        at org.apache.coyote.ajp.AjpProtocol$AjpConnectionHandler.process(AjpProtocol.java:452)--       at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:931)--      at java.lang.Thread.run(Thread.java:662)----Caused by: java.net.SocketException: Too many open files--      at java.net.Socket.createImpl(Socket.java:397)--  at java.net.Socket.<init>(Socket.java:371)--        at java.net.Socket.<init>(Socket.java:189)--   at com.edb.core.PGStream.<init>(PGStream.java:70)--     at com.edb.core.v3.ConnectionFactoryImpl.openConnectionImpl(ConnectionFactoryImpl.java:115)--   at com.edb.core.ConnectionFactory.openConnection(ConnectionFactory.java:64)--        at com.edb.jdbc2.AbstractJdbc2Connection.<init>(AbstractJdbc2Connection.java:161)--        at com.edb.jdbc3.AbstractJdbc3Connection.<init>(AbstractJdbc3Connection.java:30)-- at com.edb.jdbc3g.AbstractJdbc3gConnection.<init>(AbstractJdbc3gConnection.java:23)--   at com.edb.jdbc4.AbstractJdbc4Connection.<init>(AbstractJdbc4Connection.java:31)-- at com.edb.jdbc4.Jdbc4Connection.<init>(Jdbc4Connection.java:25)--     at com.edb.Driver.makeConnection(Driver.java:391)-- at com.edb.Driver.connect(Driver.java:266)--    at org.jboss.jca.adapters.jdbc.local.LocalManagedConnectionFactory.getLocalManagedConnection(LocalManagedConnectionFactory.java:249)--         at org.jboss.jca.adapters.jdbc.local.LocalManagedConnectionFactory.createManagedConnection(LocalManagedConnectionFactory.java:235)--         at org.jboss.jca.core.connectionmanager.pool.mcp.SemaphoreArrayListManagedConnectionPool.createConnectionEventListener(SemaphoreArrayListManagedConnectionPool.java:761)--         at org.jboss.jca.core.connectionmanager.pool.mcp.SemaphoreArrayListManagedConnectionPool.getConnection(SemaphoreArrayListManagedConnectionPool.java:343)--         at org.jboss.jca.core.connectionmanager.pool.AbstractPool.getSimpleConnection(AbstractPool.java:397)--    at org.jboss.jca.core.connectionmanager.pool.AbstractPool.getConnection(AbstractPool.java:365)--   at org.jboss.jca.core.connectionmanager.AbstractConnectionManager.getManagedConnection(AbstractConnectionManager.java:329)--         at org.jboss.jca.core.connectionmanager.tx.TxConnectionManagerImpl.getManagedConnection(TxConnectionManagerImpl.java:368)--         at org.jboss.jca.core.connectionmanager.AbstractConnectionManager.allocateConnection(AbstractConnectionManager.java:464)--         at org.jboss.jca.adapters.jdbc.WrapperDataSource.getConnection(WrapperDataSource.java:159)--         at jp.co.toyota.perz060.servlet.CCERZ060.getConnection(CCERZ060.java:489)--   at jp.co.toyota.perz060.servlet.CCERZ060.doPost(CCERZ060.java:118)--         at javax.servlet.http.HttpServlet.service(HttpServlet.java:754)--      at javax.servlet.http.HttpServlet.service(HttpServlet.java:847)-- at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:329)--  at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:248)--        at jp.co.toyota.pzy1352.util.CIZY1392.doFilter(CIZY1392.java:362)--        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:280)--  at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:248)--        at jp.co.toyota.pzy1900.util.CIZY1947.doFilter(CIZY1947.java:99)-- at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:280)--  at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:248)--        at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:275)--     at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:161)--        at org.jboss.as.web.security.SecurityContextAssociationValve.invoke(SecurityContextAssociationValve.java:153)--     at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:155)-- at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102)--     at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)--   at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:368)--     at org.apache.coyote.ajp.AjpProcessor.process(AjpProcessor.java:505)--        at org.apache.coyote.ajp.AjpProtocol$AjpConnectionHandler.process(AjpProtocol.java:452)--       at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:931)--      at java.lang.Thread.run(Thread.java:662)--
             E 2014-06-15 20:27:44.272 XML - 0 - -


問題分析:

  1. 從上面的錯誤代碼中可見“javax.resource.ResourceException: IJ000658: Unexpected throwable while trying to create a connection: null”,從經驗上判斷這可能是由於JDK版本與JDBC不匹配所造成的。當前各數據庫都有類似的操作方式,通常針對JDK 1.6以下版本,及1.6以上版本會發布不同的JDBC驅動包,以EDB爲例會有:
    edb-jdbc14.jar 對應 JDK1.6以下版本;
    edb-jdbc16.jar 對應 JDK1.6及以上版本。

  2. 由以上懷疑點要求客戶調出系統中存放JDBC驅動的目錄,發現在此目錄下同時存在以上兩個版本的jar文件,同時此目錄中有一個module.xml文件,當中內存如下:
    <modulexmlns="urn:jboss:module:1.0"name="com.edb">
        <resources>
            <resource-rootpath="edb-jdbc16.jar"/>
        </resources>
        <dependencies><modulename="javax.api"/></dependencies>
    </module>
    從此文件中可以看到JBoss中已經明確指定使用edb-jdbc16.jar,因此即使目錄中同時也有edb-jdbc14.jar,JBoss應該是不會對它進行調用的。

  3. 進一步分析,客戶告知在他們的代碼中有可能出現以下操作:
    Class.forName("com.edb.Driver");
    String url      = "jdbc:edb://xxx.xxx.xxx.xxx:5444/edb";
    String user     = "enterprisedb";
    String password = "xxxxxxx";
    Connection con  = DriverManager.getConnection(url, user, password);
    Statement stmt  = con.createStatement();
    ResultSet rs    = stmt.executeQuery("SELECT * FROM emp");
    ......
    由此推斷如果客戶代碼中存在以上操作,在運行此操作時將不授JBoss中的配置影響而直接通過JDK調用可以找到的JDBC。由於目錄中存在edb-jdbc14.jar,而從目錄的搜索角度14排在16之前,因此程序在執行以上操作時很可能會使用了edb-jdbc14.jar。在JAVA進行數據序列化操作時,因版本不對應就有可能產生以上問題。這就解析了爲何只有少量操作報連接無法找到而不是全部數據庫連接均報錯。

  4. 進一步檢查在另一套客戶的測試環境中沒有出現以上錯誤,而此測試環境下只有edb-jdbc16.jar驅動

  5. 從EDB數據庫方面分析,在數據庫日誌中並沒有在此上述時段收到連接,也沒有相應錯誤。判斷:JAVA端在獲得連接Socket端口後由於版本不對應,無法序列化,因此可能根本上就沒有發送用戶名、密碼等登陸信息,因此數據庫沒有任何日誌。

  6. 綜上所述基本定位問題所在


分析圖解:



解決方案:

  1. 申請停機時間,進行完整測試及修復;
  2. 建議將目錄中的edb-jdbc14.jar刪除;
  3. 嚴格保證日後所有項目中對應一個數據庫只有一個JDBC;
  4. 在JBoss框架下嚴格使用JNDI或其他公共方式進行連接,避免在JAVA程序中通過直接調用getConnection方式進行數據庫連接;


解決結果【未進行】:

當前以上所暴露的問題只是一個推斷,由於客戶當前是一個生產系統,無法現場進行測試及修復。【未完待續】

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章