2009-07-29 8 views
2

Je suis récemment passé à Spring Framework au lieu de gérer manuellement JDBC, et c'est surtout une bonne transition. Un programme a commencé à avoir des problèmes étranges, cependant: si la base de données est lente, en appelant getJdbcTemplate().update(...) il parfois ne revient jamais. Après une recherche un peu, je suis passé de Apache DBCP à C3PO, mais le problème est revenu.jdbcTemplate se bloque sur une longue mise à jour

Voici le code que je utilise:

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

Voici à quoi il ressemble dans le fichier journal:

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 

C'est là le code se bloque. Habituellement ça continue comme ça:

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 

Je ne sais pas pourquoi je ne reçois aucun message de la part de Spring Framework elle-même. J'ai ajouté ces lignes dans mon code principal:

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

Le message de test montre, mais rien d'autre. Désolé d'avoir divergé. J'ai remarqué un ralentissement avant le blocage. La dernière fois que la requête a été exécutée avec succès, il a fallu une minute et demie pour terminer, au lieu des 200 ms habituels. La prochaine fois, je l'ai laissé courir pendant 25 minutes avant de tuer le processus.

Je sais que j'ai des problèmes avec ma base de données (InnoDB), sur laquelle je travaille, mais après un délai d'attente, Spring Framework "abandonne" et se bloque.

Tout conseil serait apprécié.

+0

Je doute que cela ait quelque chose à voir avec Spring, c'est une jolie couche mince. cela pourrait être quelque chose à voir avec les transactions, cependant ...? – skaffman

+0

Je suis d'accord, est-il possible que vous ne fermiez pas les transactions? Est-il possible qu'une autre requête verrouille la table? Si vous utilisez InnoDB, exécutez "show innodb status" –

Répondre

2

Éventuellement, le problème a été évité en corrigeant le problème de base de données sous-jacent. J'utilisais une table InnoDB comme une file d'attente de travail, ce qui signifiait que j'avais ajouté et supprimé beaucoup d'éléments. InnoDB ne peut pas gérer ce genre de travail, ou comme le dit mon ami DBA, "supprimer des lignes d'une table ne fait rien pour la performance". Après avoir opté pour une stratégie db beaucoup plus folle, qui impliquait de créer et de supprimer des tables tout le temps, la performance était grandement améliorée et les blocages disparaissaient. Je pense que ce que je dis, c'est que le commentaire de Skaffman était probablement juste. Cela n'avait rien à voir avec Spring.

+0

peut-être vous devriez fermer la question ou supprimer l'étiquette de printemps? – iwein