2009-07-29 15 views
2

Ich habe vor kurzem auf Spring Framework gewechselt, anstatt manuell JDBC zu behandeln, und es ist meistens ein guter Übergang. Ein Programm hatte jedoch seltsame Probleme: Wenn die Datenbank langsam ist, wird sie beim Aufruf von getJdbcTemplate().update(...) manchmal nie zurückgegeben.jdbcTemplate hängt am langen Update

Nach ein wenig Forschung, ich wechselte von Apache DBCP zu C3PO, aber das Problem kam immer noch zurück.

Hier ist der Code, den ich mit:

public class MyDao extends SimpleJdbcDaoSupport { 
    private static Logger logger = Logger.getLogger(MyDao.class); 

    public MyDao(Config config) { 
     super(); 

     ComboPooledDataSource cpds = new ComboPooledDataSource(); 
     try { 
      cpds.setDriverClass("com.mysql.jdbc.Driver"); 
     } catch (PropertyVetoException e) { 
      throw new RuntimeException(e); 
     } 
     cpds.setUser("username"); 
     cpds.setPassword("password"); 
     cpds.setJdbcUrl("jdbc:mysql://localhost/schema" + 
         "?useUnicode=true&characterEncoding=UTF-8"); 
     cpds.setMaxStatements(180); 
     cpds.setPreferredTestQuery("SELECT 1"); 
     cpds.setTestConnectionOnCheckout(true); 

     this.setDataSource(cpds); 
    } 

    public void addToWorkQueue(String item) { 
     long[] ids = Utils.getItemIds(item); 

     try { 
      logger.debug("About to insert to work table"); 
      getJdbcTemplate().update(
        "INSERT IGNORE INTO work " + 
        "SELECT * FROM queue WHERE id_1 = ? AND id_2 = ?", 
        new Object[] { ids[0], ids[1] } 
      ); 
     } finally { 
      logger.debug("Updated work table"); 
     } 
    } 
} 

Hier ist, wie es in der Protokolldatei aussieht:

2009-07-29 17:37:13.570 com.mycomp.MyDao About to insert into work table 
2009-07-29 17:37:13.570 com.mchange.v2.c3p0.impl.C3P0PooledConnectionPool Testing PooledConnection [[email protected]] on CHECKOUT. 
2009-07-29 17:37:13.571 com.mchange.v2.c3p0.stmt.GooGooStatementCache checkinAll(): com.mchange.v2.c3p0.stmt.GlobalMaxOnlyStatementCache stats -- total size: 1; checked out: 0; num connections: 1; num keys: 1 
2009-07-29 17:37:13.571 com.mchange.v2.c3p0.impl.C3P0PooledConnectionPool Test of PooledConnection [[email protected]] on CHECKOUT has SUCCEEDED. 
2009-07-29 17:37:13.571 com.mchange.v2.resourcepool.BasicResourcePool trace [email protected] [managed: 3, unused: 2, excluded: 0] (e.g. [email protected]) 
2009-07-29 17:37:13.571 com.mchange.v2.c3p0.stmt.GooGooStatementCache com.mchange.v2.c3p0.stmt.GlobalMaxOnlyStatementCache ----> CACHE HIT 
2009-07-29 17:37:13.571 com.mchange.v2.c3p0.stmt.GooGooStatementCache checkoutStatement: com.mchange.v2.c3p0.stmt.GlobalMaxOnlyStatementCache stats -- total size: 1; checked out: 1; num connections: 1; num keys: 1 

Dies ist, wo der Code hängt. Normalerweise geht es einfach so weiter:

2009-07-29 17:37:13.762 com.mchange.v2.c3p0.stmt.GooGooStatementCache checkinStatement(): com.mchange.v2.c3p0.stmt.GlobalMaxOnlyStatementCache stats -- total size: 1; checked out: 0; num connections: 1; num keys: 1 
2009-07-29 17:37:13.763 com.mchange.v2.c3p0.stmt.GooGooStatementCache checkinAll(): com.mchange.v2.c3p0.stmt.GlobalMaxOnlyStatementCache stats -- total size: 1; checked out: 0; num connections: 1; num keys: 1 
2009-07-29 17:37:13.763 com.mchange.v2.resourcepool.BasicResourcePool trace [email protected] [managed: 3, unused: 2, excluded: 0] (e.g. [email protected]) 
2009-07-29 17:37:13.763 com.mycomp.MyDao Updated work table 

Ich weiß nicht, warum ich keine Protokollmeldung von Spring Framework selbst bekomme. Ich habe diese Zeilen in meinem Hauptcode hinzugefügt:

Logger springLogger = Logger.getLogger("org.springframework"); 
springLogger.setLevel(Level.TRACE); 
springLogger.debug("testing spring logger"); 

Die Testnachricht zeigt, aber sonst nichts. Sorry für divergieren.

Ich bemerkte eine Verlangsamung vor dem Aufhängen. Das letzte Mal, als die Abfrage erfolgreich ausgeführt wurde, dauerte es eineinhalb Minuten bis zum Ende, anstatt der üblichen 200 ms. Das nächste Mal ließ ich es für 25 Minuten laufen, bevor ich den Prozess beendete.

Ich weiß, ich habe ein paar Probleme mit meiner Datenbank (InnoDB), an der ich arbeite, aber das scheint nach einer Zeitüberschreitung, Spring Framework nur "aufgegeben" und hängt.

Jeder Rat würde geschätzt werden.

+0

Ich bezweifle, dass dies etwas mit Spring zu tun hat, es ist eine ziemlich dünne Schicht. es könnte etwas mit Transaktionen zu tun haben, obwohl ...? – skaffman

+0

Ich stimme zu, ist es möglich, dass Sie keine Transaktionen abschließen? Ist es möglich, dass eine andere Abfrage die Tabelle sperrt? Wenn Sie InnoDB verwenden, führen Sie "show innodb status" –

Antwort

2

Schließlich wurde das Problem vermieden, indem das zugrundeliegende DB-Problem behoben wurde.

Ich habe eine InnoDB-Tabelle als Arbeitswarteschlange verwendet, was bedeutete, dass ich eine ganze Reihe von Elementen hinzugefügt und entfernt habe. Die Tabelle hatte zu einem bestimmten Zeitpunkt nie zu viele Zeilen, aber anscheinend kann InnoDB mit dieser Art von Arbeit nicht umgehen, oder, wie mein DBA-Freund es ausdrückte, "das Löschen von Zeilen aus einer Tabelle macht nichts für die Leistung".

Nach dem Wechsel zu einer viel verrückteren db-Strategie, die das Erstellen und Löschen von Tabellen zu jeder Zeit beinhaltete, wurde die Leistung stark verbessert und die Hangs gingen weg.

Also ich denke, was ich sage ist, Skaffmans Kommentar war wahrscheinlich richtig. Das hatte nichts mit Spring zu tun.

+0

aus, vielleicht sollten Sie die Frage schließen oder das Spring-Tag entfernen? – iwein