【发布时间】:2014-07-09 05:33:48
【问题描述】:
我有一段代码可以更新数据库中的记录。简化示例:
...
statement = connection.prepareStatement(
"INSERT INTO thistable (name) VALUES (?)",
PreparedStatement.RETURN_GENERATED_KEYS
);
statement.setString( 1, "Fred" );
statement.addBatch( );
statement.setString( 2, "Joe" );
statement.addBatch( );
statement.executeBatch( );
...
这是处理大量记录的某些代码的一部分,并且该代码正在运行大量线程以提高速度。这一切都很好,但是随着实时环境的负载增加,我注意到一些SQLTransientExceptions 被抛出。除了重试事务,我似乎无能为力。
我的问题是:即使语句失败,批次是否已被清除?我可以简单地重试executeBatch 行,还是需要重新创建整个批次?非批处理语句也一样吗?
简而言之,更一般地说,这是处理瞬态异常的好方法吗?
statement.setString( 1, "Fred" );
statement.addBatch( );
statement.setString( 2, "Joe" );
statement.addBatch( );
for( int attempt = 0; ; attempt ++ ) {
try {
statement.executeBatch( );
break;
} catch( SQLTransientException ex ) {
if( attempt >= 3 ) {
throw ex;
}
try {
Thread.sleep( attempt * attempt * 100 );
} catch( InterruptedException ex2 ) {
throw ex;
}
}
}
【问题讨论】:
-
我已经标记了这个问题 MySQL,因为这是我们目前正在使用的,但我希望了解标准行为,而不是特定于实现的行为,因为我们很快就会迁移到 Postgres .
-
理论上
SQLTransientException应该只在错误允许可以在没有“应用程序级功能的任何干预”的情况下重试的操作时抛出。 -
您是否有任何 SQL 状态用于此异常 (getSQLState())?
-
@Mani,恐怕我不知道它的存在所以我没有记录它。
-
@user2574853的回答评论:虽然我贴的例子没有说明,但每批添加的10条左右的记录确实是一批;它们都与同一个项目相关,如果其中任何一个失败,则添加其他项目毫无意义。