質問
最近、JDBCを手動で処理するのではなく、Spring Frameworkに切り替えました。これは、ほとんどの場合、良い移行です。しかし、1つのプログラムに奇妙な問題が発生し始めました。データベースが遅い場合、 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");
テストメッセージは表示されますが、他には何も表示されません。発散して申し訳ありません。
ハングする前に速度が低下したことに気付きました。クエリが正常に最後に実行されたとき、通常の200ミリ秒ではなく、1分半かかりました。次回は、プロセスを強制終了する前に25分間実行しました。
作業中のデータベース(InnoDB)に問題があることは知っていますが、これはタイムアウト後、Spring Frameworkが「あきらめ」ます。ハングします。
アドバイスをいただければ幸いです。
解決
最終的には、基礎となるDBの問題を修正することで問題を回避しました。
InnoDBテーブルを作業キューとして使用していたため、大量のアイテムを追加および削除しました。一度にテーブルに行が多くなりすぎることはありませんでしたが、明らかにInnoDBはこの種の作業を処理できません。 p>
常にテーブルの作成と削除を行う、非常にクレイジーなdb戦略に切り替えた後、パフォーマンスは大幅に改善され、ハングはなくなりました。
だから私が言っていることは、スカッフマンのコメントはおそらく正しかったと思います。これは、Springとは関係ありませんでした。