2017-05-12 2 views
1

Wir haben eine Multi-threaded Java-Anwendung mit einer Web-UI und REST-API, die mit Java 6 kompiliert und in Tomcat 6 ausgeführt wird. Während Operationen verwendet OJDBC auf seine Oracle DB zugreifen Millionen Mal am Tag. Alle zwei oder drei Monate hängt eine der DB-Abfragen und wird nie zurückgegeben, wodurch ein Teil der Anwendung die Verarbeitung beendet und ein Rückstand erstellt wird. Andere Threads können mit der DB kommunizieren und ihre Arbeit erledigen, nur ein Thread wird gehängt, was leider die Dateiverarbeitung stoppt.Java OJDBC Oracle SQL-Abfrage hängt alle paar Monate einmal

Ein Thread-Dump zeigt, dass der Faden aus der Steckdose wird das Auslesen der nie mal noch geschlossen wird:

"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) 

Wenn dies die DBAs geschieht auf dem DB-Server ausgesehen hat und keine lange Lauf Abfrage sehen . Die Lösung ist Tomcat zu recyceln, was das Problem behebt, aber ich möchte herausfinden, ob es einen programmatischen Weg gibt, um damit umzugehen. Ich habe Anhänge gesehen, die sich auf ähnliche Probleme beziehen, die behoben werden, indem die LINUX-Box, auf der der DB-Server läuft, recycelt wird, aber das ist für uns keine Option; Ich brauche eine Korrektur auf Anwendungsebene.

Die DB Ressource verwendet definiert:

<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 Treiber verwendet wird, ist: ojdbc6_g-11.2.0.4.0.jar

Die DB-Version ist: 11.2.0.3.0

der Java-Code die Abfrage ausgeführt wird:

   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(); 

Dies ist die Quelle für getConnection():

"ds" ist definiert als: private statische DataSource ds = null; und wird unter Verwendung initialisiert:

 Context initContext = new InitialContext(); 
     ds = (DataSource)initContext.lookup(wrapper.getCSADBJNDIName()); 

Antwort

1

Nach meiner Erfahrung dieser Fehler typischerweise ein Netzwerk ist. Ihre Abfrage wurde abgeschlossen, aber Ihr Client blockiert immer noch eine Netzwerkantwort, die er nie erhalten wird. Dies ist der Grund, warum der App-Server springt, da er alles auf dem App-Server zurücksetzt, aber das Springen auf den DB-Server macht keinen Sinn, da es sich nicht um ein DB-Problem handelt. Werfen Sie einen Blick auf diese Frage/Antwort auf dieser Seite ...

Question on network timeouts

+0

Ich bin damit einverstanden @unleashed, mögliche Netzfehler, könnte aber auch langsame Client-Seite Verarbeitung oder auch eine zu geringe sein Array-Fetch-Größe, die zu viele Netzwerk-Roundtrips verursachen würde ["SQL * Net ist ein gesprächiges Protokoll"]. In diesem Fall wird durch das Prellen des App-Servers die anstößige Leerlaufsitzung beendet, die den Engpass darstellt. –

+0

Vielen Dank sowohl für die Antworten und die Referenzen, sehr nützlich.Der Netzwerkfehler erscheint in diesem Fall viel plausibler. Wie der obige Code zeigt, wird Tomcat-DB-Ressource verwendet. Gibt es eine Möglichkeit, ein Timeout in Tomcat zu definieren, anstatt den DriverManager zu verwenden? – user3722575

1

Überprüfen Sie, ob die Sitzung:

  1. inaktiv - wenn inaktiv, was die Wartezustand ist, kann es sein, Warten auf Client oder Netzwerk.
  2. Es gibt blockierende Sperren, die die Leerlaufsitzung betreffen (z. B. hält es einige Sperren für nicht festgeschriebene Transaktionen).

Überprüfen Sie auch für den Anschluss Stürme (dh zu viele Sitzungen die Instanz schlagen kann schwerwiegende Probleme verursachen CPU)

+0

Der DBA sieht die Sitzung/Abfrage auf dem Server nicht. Thread-Dump aus meiner App zeigt: "Fileupload" Daemon Prio = 10 tid = 0x00002af6d42c8000 nid = 0x369 runnable [0x00002af6d87fe000] java.lang.Thread.State: RUNNABLE \t bei java.net.SocketInputStream.socketRead0 (native Methode) I bin mir sicher, dass es sich nicht um ein Verbindungssturmproblem handelt. Ich habe diese beiden zu tomcat resource definition hinzugefügt, aber sehe keinen Protokolleintrag als Ergebnis: validationQueryTimeout = "3600" suspectTimeout = "60" In der Hoffnung auf eine Eingabe – user3722575

+0

Volle Ressource Definition: user3722575

Verwandte Themen