jdbcTemplate在长时间更新时挂起
我最近切换到Spring框架,而不是手动处理JDBC,这是一个很好的过渡。不过,有一个程序开始出现奇怪的问题:如果数据库运行缓慢,在调用jdbcTemplate在长时间更新时挂起,jdbc,spring,c3p0,Jdbc,Spring,C3p0,我最近切换到Spring框架,而不是手动处理JDBC,这是一个很好的过渡。不过,有一个程序开始出现奇怪的问题:如果数据库运行缓慢,在调用getJdbcTemplate().update(…)时,它有时永远不会返回 在研究了一点之后,我从ApacheDBCP切换到了,但问题还是回来了 以下是我使用的代码: public class MyDao extends SimpleJdbcDaoSupport { private static Logger logger = Logger.getLo
getJdbcTemplate().update(…)
时,它有时永远不会返回
在研究了一点之后,我从ApacheDBCP切换到了,但问题还是回来了
以下是我使用的代码:
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");
}
}
}
以下是日志文件中的内容:
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 [com.mchange.v2.c3p0.impl.NewPooledConnection@170984c] 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 [com.mchange.v2.c3p0.impl.NewPooledConnection@170984c] on CHECKOUT has SUCCEEDED.
2009-07-29 17:37:13.571 com.mchange.v2.resourcepool.BasicResourcePool trace com.mchange.v2.resourcepool.BasicResourcePool@d402dd [managed: 3, unused: 2, excluded: 0] (e.g. com.mchange.v2.c3p0.impl.NewPooledConnection@170984c)
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
这就是代码挂起的地方。通常是这样的:
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 com.mchange.v2.resourcepool.BasicResourcePool@d402dd [managed: 3, unused: 2, excluded: 0] (e.g. com.mchange.v2.c3p0.impl.NewPooledConnection@170984c)
2009-07-29 17:37:13.763 com.mycomp.MyDao Updated work table
我不知道为什么我没有从Spring框架本身得到任何日志消息。我在主代码中添加了以下行:
Logger springLogger = Logger.getLogger("org.springframework");
springLogger.setLevel(Level.TRACE);
springLogger.debug("testing spring logger");
测试消息显示,但没有其他内容。对不起,有分歧
在绞刑前我确实注意到了减速。上次查询成功运行时,需要一分钟半的时间才能完成,而不是通常的200毫秒。下一次,我让它运行25分钟,然后停止进程
我知道我正在处理的数据库(InnoDB)有一些问题,但这似乎是在超时之后,Spring框架“放弃”并挂起
如果您有任何建议,我们将不胜感激。最终,通过修复基础数据库问题,问题得以避免 我使用InnoDB表作为工作队列,这意味着我在其中添加和删除了很多项。该表在给定的时间内从来没有太多行,但显然InnoDB无法处理此类工作,或者正如我的DBA朋友所说,“从表中删除行对性能没有任何影响” 在切换到更疯狂的db策略(该策略涉及始终创建和删除表)之后,性能得到了很大提高,挂起也消失了
所以我想我说的是,斯卡夫曼的评论可能是正确的。这与弹簧没有任何关系。我怀疑这与弹簧有任何关系,它是一层很薄的层。这可能与交易有关,不过…?我同意,你有可能不关闭交易吗?是否有可能另一个查询会锁定该表?如果您正在使用InnoDB,请运行“show InnoDB status”,也许您应该关闭该问题或删除spring标记?