jdbcTemplate 在长时间更新时挂起

标签 jdbc spring c3p0

我最近切换到 Spring Framework 而不是手动处理 JDBC,这主要是一个很好的过渡。但是,一个程序开始出现奇怪的问题:如果数据库速度很慢,则在调用 getJdbcTemplate().update( ... ) 时,它有时永远不会返回。

经过一些研究,我从 Apache DBCP 切换到 C3PO , 但问题还是来了。

这是我使用的代码:

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 Framework 本身收到任何日志消息。我在我的主要代码中添加了这些行:

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

测试消息显示,但没有其他内容。很抱歉出现分歧。

我确实注意到在挂起之前速度变慢了。上次查询成功运行用了 1.5 分钟完成,而不是通常的 200 毫秒。下一次,我让它运行 25 分钟,然后终止进程。

我知道我正在处理的数据库 (InnoDB) 有一些问题,但这似乎是在超时之后,Spring Framework 只是“放弃”并挂起。

如有任何建议,我们将不胜感激。

最佳答案

最终,通过修复底层数据库问题避免了该问题。

我使用 InnoDB 表作为工作队列,这意味着我向其中添加和删除了很多项目。该表在给定时间从来没有太多行,但显然 InnoDB 无法处理此类工作,或者正如我的 DBA friend 所说,“从表中删除行对性能没有任何影响”。

在切换到更疯狂的数据库策略(始终涉及创建和删除表)之后,性能得到了很大改善,挂起现象也消失了。

所以我想我的意思是,skaffman 的评论可能是正确的。这与 Spring 没有任何关系。

关于jdbcTemplate 在长时间更新时挂起,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1200852/

相关文章:

java - 属性文件中的占位符在目标中不会被 maven 替换

java - 使用 Java/Scala 存储/检索 BYTEA 和 BLOB : "java.sql.SQLFeatureNotSupportedException"

java - JDBCTemplate + MySQL 主键转外键

java - Spring 持久失败,带有 FK 的 JSON,FK null

java - 使用 Java 而不是 XML 在 Spring 下配置 Logback

java - 达到 max_size 时 c3p0 不释放连接

java - org.apache.commons.dbcp.DelegatingPreparedStatement 已关闭

java - Spring 4 不会自动限定 Autowiring 上的泛型类型

java - c3p0 连接池,DataSources 工厂,如何关闭池?

使用 c3p0 和 Tomcat : too many connections hibernate