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.
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
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" –