2017-02-13 1 views
2

Ich habe eine 24/7 Java-Anwendung (jdk1.5.0_19), die Multi-Thread ist, die OJDBC5 als die Kommunikation für Oracle 11g (11.2.0.3) verwendet. Nach dem Verifizieren des Inhalts des Threads ruft jeder Thread eine aufzulösende Anweisung auf, die vorbereitet wird, und führt dann aus, um Daten in die Tabelle einzufügen. Jetzt bei der Initialisierung gibt es eine Total JDBC 20 Connections. Seit einiger Zeit geht es wirklich gut, keine Probleme.Connection Pool hängt mit Java Multi-Thread-Programm

Aber vor kurzem gab es eine Instanz, wo es gerade während der Ausführung der aufrufbaren Anweisung in DB gehängt wurde.

2017-02-06 13:03:39,855 [Thread-1] INFO QCCOM_SocketWorker run - Worker thread launched. 
2017-02-06 13:03:39,856 [Thread-1] INFO QCCOM_Socket recvMessage 
2017-02-06 13:03:39,856 [Thread-1] INFO QCCOM_SocketWorker recvRequest 
2017-02-06 13:03:39,856 [Thread-1] INFO ProcessHandler invoke 
2017-02-06 13:03:39,856 [pool-1-thread-1] INFO HandlerValidator validateRequest 
2017-02-06 13:03:39,857 [pool-1-thread-1] INFO ProcessHandler process - Processing request... 
2017-02-06 13:03:39,857 [pool-2-thread-1] INFO JDBCHelper call - Atempting to retrieve connection. 
2017-02-06 13:03:39,857 [pool-2-thread-1] INFO JDBCHelper call - Connection successfully retrieved 
2017-02-06 13:03:39,857 [pool-1-thread-1] INFO JDBCHelper getConnection - Conn : [email protected] 
2017-02-06 13:03:39,858 [pool-1-thread-1] INFO JDBCServiceImpl insertBP - Calling insert transaction stored procedure.. 
2017-02-06 13:03:43,856 [Thread-1] INFO ProcessHandler invoke - Worker Thread Timed out 
2017-02-06 13:03:43,857 [Thread-1] DEBUG ProcessHandler invoke - [java.util.concurrent.FutureTask$Sync.innerGet(FutureTask.java:226), java.util.concurrent.FutureTask.get(FutureTask.java:100), ....ProcessHandler.invoke(ProcessHandler.java:114), com.qcom.qcm.qccom.QCCOM_SocketWorker.dispatch(QCCOM_SocketWorker.java:88), com.qcom.qcm.qccom.QCCOM_SocketWorker.run(QCCOM_SocketWorker.java:126)] 
2017-02-06 13:03:43,857 [Thread-1] INFO QCCOM_SocketWorker run - Worker thread shutdown. 
2017-02-06 13:03:55,661 [pool-1-thread-1] INFO JDBCServiceImpl insertBP - Callable Statement successfully closed! 
2017-02-06 13:03:55,661 [pool-1-thread-1] INFO JDBCServiceImpl insertBP - Connection successfully closed! 
2017-02-06 13:03:55,662 [pool-1-thread-1] INFO ProcessHandler process - Connection successfully closed! 

Normalerweise passiert die Transaktion weniger als weniger als 200ms.

2017-02-06 13: 03: 39.858 [Pool-1-Faden-1] INFO JDBCServiceImpl insertBP - Berufung Einsatz Transaktion gespeicherte Prozedur ..

Aber im Beispiel oben haben wir einen hängen die Ausführung von Einfügen.

Siehe Code unten (JDBCServiceImpl insertBP).

public synchronized void insertBP(String A, BigDecimal Num, Date Date) throws SQLException{ 
    CallableStatement cs = null; 
    logger.info("Calling insert transaction stored procedure.."); 
    try{ 
     cs = (CallableStatement) conn.prepareCall("{"+sql+"}"); 
     cs.setString(1, tnxType); 
     cs.setBigDecimal(2, Num); 
     cs.setTimestamp(3, new Timestamp(Date.getTime())); 

     cs.execute(); 
    } catch (SQLException sqlEx){   
     String strMessageContents = StringUtil.getFailedMessageContents(A, Num, Date); 
     String strErrorMessage = "Failed to insert "; 
     logger.fatal(strErrorMessage); 
     aUtil.emailFatal; 
     throw sqlEx; 
    } finally { 
     if (null!=cs){ 
      cs.close(); 
      logger.info("Callable Statement successfully closed!"); 
     } 
     if (null!=conn){ 
      conn.close(); 
      logger.info("Connection successfully closed!"); 
     } 
    } 
} 

Irgendwie hängt es auf cs.execute ... Dann Timeout Worker-Thread kommt und tötet die gesamte Transaktion, aber irgendwie ist es nicht die bereits eingeleiteten aufrufbaren Anweisung töten.

Ich habe auch einen Code für fail over, der die Hauptverbindung tötet, durch diese Methode wird die gesamte Verbindung getötet, was zu erfolgreichem Töten führt.

2017-02-06 13: 03: 55,661 [pool-1-thread-1] INFO JDBCServiceImpl insertBP - Callable Statement erfolgreich geschlossen!

-Code ist wie für Util

public void destroyHelper(){ 
    AppJDBCHelper helper = null; 
    try { 
     helper = AppJDBCHelper.getInstance(); 
     helper.destroy(); 
    } catch (SQLException e) { 
     logger.fatal(e); 
     logger.debug(Arrays.toString(e.getStackTrace())); 
    }  
} 

Zusatzcode für AppJDBCHelper

public void destroy() throws SQLException{ 
    DBConnectionPool pool = new DBConnectionPoolImpl(); 
    pool.closeConnectionPool(ods); 
    helper = null; 
    logger.info("AppJDBCHelper destroy() success..."); 
} 

Diese zwei Maschinen befinden sich im gleichen Schalter

if (Util.IsOffline){ 
    logger.info("App is Offline attempting to reestablish connection."); 
    Util.destroyHelper(); 
    logger.info("Previous Connection Pool Destroyed..."); 
    logger.info("Reinitializing Connection Pool ..."); 
    try { 
     AppJDBCHelper helper = AppJDBCHelper.getInstance(); 
     if (null != helper){ 
      logger.info("Connected to Schema: "+helper.getSchema()); 
      logger.info("Connection Pool initialized ..."); 
      Util.IsOffline = false; 
      logger.info("App has reestablished connection."); 
     } 
     if (null == helper){ 
      logger.fatal("Failed to get database connection pool ..."); 
      Util.destroyHelper(); 
     } 
    } catch (SQLException e){ 
     logger.fatal("Failed to connect to database ..."); 
     logger.debug(Arrays.toString(e.getStackTrace())); 
     System.out.println(" \n >>> ERROR: Failed to connect to database ..."); 
     Util.destroyHelper(); 
    } 
} 

Zusätzlicher Code folgt, so ist es weniger Netzwerkreibung. und wie überprüft, gibt es keine Netzwerkprobleme während dieser Zeit. Auch DB Listener ist aktiv und war bereit Transaktionen zu akzeptieren.

Also meine Hauptfrage hier ist, was zum Teufel passiert und die aufrufbare Aussage hängt.

+2

In der JVM wurden seit April 2009 Hunderte, wenn nicht Tausende von Fehlern behoben. Wenn Sie merkwürdiges Verhalten feststellen, möchten Sie es vielleicht mit einer neueren JVM oder sogar der neuesten später veröffentlichten Version von Java 5.0 testen Jahr. –

+0

Yeah verstanden Ich habe dies auch vorgeschlagen, aber Client will immer noch nicht Java-Version zu aktualisieren. –

+0

Verstanden. Können Sie sich mit einer Arbeit herumschlagen, wenn eine Lösung nicht offensichtlich erscheint? –

Antwort

0

Ein möglicher Ansatz besteht darin, nach unten zu gehen und zuerst zu prüfen, ob es Probleme in der Datenbank gab. Wenn Sie auf Oracle 11g sind, ist es eine gute Änderung, die Sie auch eine Lizenz von ASH

Überprüfen Sie die Datenbank (oder kontaktieren Sie Ihren DBA) mit der folgenden Abfrage haben, wo Sie die Zeit intrval und Ihre Verbindungspool DBUSER parametrisieren. (Wenn das Problem in der Vergangenheit aufgetreten ist, wechseln Sie in die Tabelle dba_hist_active_sess_history, die ein längeres Zeitintervall enthält.

select 
SAMPLE_TIME, SQL_EXEC_ID, SESSION_ID, SESSION_SERIAL#, SQL_ID, TOP_LEVEL_SQL_ID, SQL_OPNAME, 
PLSQL_ENTRY_OBJECT_ID, EVENT, BLOCKING_SESSION_STATUS, BLOCKING_SESSION, BLOCKING_SESSION_SERIAL# 
select * from v$active_session_history 
where sample_time between to_date('15022017 214500','ddmmyyyy hh24miss') and to_date('15022017 215000','ddmmyyyy hh24miss') 
and USER_ID in (select user_id from dba_users where username = '<your user name>') 
order by session_id, SESSION_SERIAL#,SAMPLE_TIME; 

Hier ist ein Beispiel für die Ausgabe, ein INSERT durch eine Tabellensperre blockiert simuliert.

SAMPLE_TIME     SESSION_ID SESSION_SERIAL# SQL_ID  TOP_LEVEL_SQL_ID SQL_OPNAME PLSQL_ENTRY_OBJECT_ID EVENT     BLOCKING_SESSION_STATUS BLOCKING_SESSION BLOCKING_SESSION_SERIAL# 
--------------------------- ---------- --------------- ------------- ---------------- ----------- --------------------- ----------------------- ----------------------- ---------------- ------------------------ 
15.02.17 21:45:20,669000000   11   10976 gr2assvfzr2v7 6j87w7zmmzpsk INSERT      154744 enq: TM - contention VALID         13      4283 
15.02.17 21:45:21,683000000   11   10976 gr2assvfzr2v7 6j87w7zmmzpsk INSERT      154744 enq: TM - contention VALID         13      4283 
15.02.17 21:45:22,682000000   11   10976 gr2assvfzr2v7 6j87w7zmmzpsk INSERT      154744 enq: TM - contention VALID         13      4283 
15.02.17 21:45:23,680000000   11   10976 gr2assvfzr2v7 6j87w7zmmzpsk INSERT      154744 enq: TM - contention VALID         13      4283 
15.02.17 21:45:24,679000000   11   10976 gr2assvfzr2v7 6j87w7zmmzpsk INSERT      154744 enq: TM - contention VALID         13      4283 
15.02.17 21:45:25,693000000   11   10976 gr2assvfzr2v7 6j87w7zmmzpsk INSERT      154744 enq: TM - contention VALID         13      4283 
15.02.17 21:45:26,691000000   11   10976 gr2assvfzr2v7 6j87w7zmmzpsk INSERT      154744 enq: TM - contention VALID         13      4283 
15.02.17 21:45:27,689000000   11   10976 gr2assvfzr2v7 6j87w7zmmzpsk INSERT      154744 enq: TM - contention VALID         13      4283 

Der inportant informaton ist der Zeitstempel, die Sitzungsidentifikation, die SQL-Operation (INSERT erwarten) und das Ereignis. In meinem Beispiel sehen Sie EVENT enq: TM - contention, dh die Tabelle ist gesperrt und die Sitzung kann die Einfügung nicht durchführen. Natürlich können Sie ein anderes Ereignis sehen - überprüfen Sie die Oracle documentation, um die Problemursache zu beheben. Schließlich sehen Sie die Blockierungsstatus und Blockierungssitzung, die die Lösung bieten kann, warum das Problem aufgetreten ist.

Falls Sie keine verdächtigen Beweise in der Datenbank sehen (blockierende oder wartende Zustände), gehen Sie vor und überprüfen Sie die Protokolle Ihrer Anwendung.

+0

Vielen Dank für den Vorschlag und wird DBA fragen, um Details zur Verfügung zu stellen. Aber ich erinnere mich, dass sie sagten, es gäbe keine Schlösser. Zeigt dies andere Probleme an, die möglicherweise vorhanden sind, außer dem Sperren? –

+0

@Kyle ASH ** wurde entwickelt, um solche Probleme zu beheben **. Vorübergehend, wenn sie in der Vergangenheit passieren. Sie sehen einen periodischen Snapshot aller aktiven Sitzungen. Es ist nicht auf das Blockieren beschränkt, Sie sehen Sessions, die die CPUs verarbeiten oder auf I/O warten. Dokumentieren Sie, spielen Sie damit in Ihrer Entwicklungs-DB und * bevorzugt * Anfrage Zugriff für die produktive DB. Gutes Schloss! –

+0

Hallo und danke für die Köpfe hoch. Jedenfalls habe ich unseren Datenbankadministrator gebeten, ausgewählte Abfragen auszuführen, und er gab "keine Zeilen ausgewählt" aus. scheint es gab keine Probleme während dieser Zeit oder es wurde nicht vollständig aufgezeichnet. Irgendwelche anderen Vorschläge, die ich überprüfen kann, während DB-Team dies prüft? –