我在数百万条记录上使用了批更新准备语句,但在执行>400k条记录后,最终在运行时遇到了以下错误。
java.sql.sql异常:ORA-01000:超过的最大打开游标数
我不知道这是否是由以下代码引起的
try{
conn = ConnectionManager.getConnection();
// turn off autocommit
conn.setAutoCommit(false);
PreparedStatement stmt = conn.prepareStatement(query);
//for each of the records to be updated
for(int k=0;k<objects.length;k++) {
stmt.setString(1, objects[k].getValueA());
stmt.setString(2, objects[k].getValueB());
stmt.addBatch();
//running batch execute on every 10000 records
if(k%10000 == 0 || k == objects.length-1) {
// submit the batch for execution
int[] updateCounts = stmt.executeBatch();
conn.commit();
if(k < objects.length-1)
{
stmt.close();
stmt = conn.prepareStatement(query);
}
}
}
}catch( Exception e ) {
e.printStackTrace();
}finally {
if(conn!=null){
conn.close();
}
}
从而在提交连接之后关闭PreparedStatement并用新的PreparedSStatement替换。我不确定重复提交同一连接是否会导致此问题。
有人能为这个问题提出解决方案吗?或者建议更好的体系结构来处理准备好的语句的批量更新吗。
p/S:错误行实际上指向删除语句执行,但我不认为这是根本原因,因为之前添加了批更新准备的语句代码之前,这个问题不存在。
try {
if ( hasData ) {
conn = ConnectionManager.getConnection();
CommonStore.deleteRecords( conn, queryStr ); //the error point to this line
hasData = false;
}
}catch( Exception e ) {
e.printStackTrace();
}finally {
if(conn!=null){
conn.close();
}
}
感谢您的任何建议
我观察到的一件事是:
if(k < objects.length-1)
{
stmt.close();
stmt = conn.prepareStatement(query);
}
我建议重用stmt
对象,而不是closing
。这只是可以避免的开销。
我认为关闭并重新打开同一个PreparedStatement
没有任何作用。此外,您可以考虑在addBatch()
之后调用PreparedStatement.clearParameters()