oracle 执行部分故障时的批处理行为

a0zr77ik  于 2022-11-03  发布在  Oracle
关注(0)|答案(3)|浏览(233)

我有一个java 1.6应用程序,它使用batch insert通过jdbc驱动程序在Oracle数据库中插入记录。(),我们使用它来进行批处理更新。它有一个返回类型为int的数组,其中包含每个记录的执行结果。但它也会在出错时抛出BatchUpdateException,我们也可以从中获取结果int数组。我的问题是,在什么错误情况下,我应该预期BatchUpdateException,在什么情况下,我应该预期没有抛出异常,但对于一些记录,我得到了失败。
注意:这个问题是专门针对Oracle JDBC的。为了更清楚地说明问题,我看到过在执行executeBatch()后没有得到BatchUpdateException的情况,但是一些插入语句失败了。我的问题是在什么情况下会发生这种情况?
这是Statement.executeBatch()方法的返回javadoc。根据这里的一般意见,当一个条目失败时,执行会抛出BatchUpdateException,然后在这种情况下,我们可以预期返回数组中的一些条目失败。


* @return an array of update counts, with one entry for each command in the

 *         batch. The elements are ordered according to the order in which
 *         the commands were added to the batch.
 *         <p>
 *         <ol>
 *         <li> If the value of an element is >=0, the corresponding command
 *         completed successfully and the value is the update count for that
 *         command, which is the number of rows in the database affected by
 *         the command.</li>
 *         <li> If the value is SUCCESS_NO_INFO, the command completed
 *         successfully but the number of rows affected is unknown.
 *         <li>
 *         <li> If the value is EXECUTE_FAILED, the command failed.
 *         </ol>
 * @throws SQLException
 *             if an error occurs accessing the database
 */
public int[] executeBatch() throws SQLException;
bvn4nwqk

bvn4nwqk1#

假设您有5个批次更新陈述式,每个陈述式的执行都是要更新20笔预先知道的记录。
执行更新陈述式批次时,不会掷回BatchUpdateExceptionSQLException
如果返回的int数组中有任何元素不是20,那么你就知道有意外的行为。这可以被看作是一个失败。

编辑

来自BatchUpdateExcpetion的JavaDoc(突出显示部分是我添加的)
在批处理更新中的命令无法正确执行并引发BatchUpdateException后,驱动程序可能会也可能不会继续处理批处理中的其余命令。如果驱动程序在失败后继续处理,由方法BatchUpdateException.getUpdateCounts返回的数组对于批处理中的每个命令都将具有一个元素,而不仅仅是对于在错误之前成功执行的命令的元素。在驱动程序停止 [ed] 处理命令的情况下,任何失败的命令的数组元素都是Statement.EXECUTE_FAILED。
我的理解是,如果批处理中的任何语句失败,则将抛出BatchUpadteException

yqhsw0fo

yqhsw0fo2#

如果在批处理过程中发生错误,Oracle JDBC驱动程序将引发BatchUpdateException。
例如,假设您要发送一个包含10个条目的批处理(在您的情况下要插入10行)。条目#0到#4成功。条目#5遇到了一个错误,例如主键冲突。执行在5处停止,驱动程序抛出BatchUpdateException。如果您调用getUpdateCounts(),您将得到一个大小为10的数组,其中包含5个SUCCESS_NO_INFO和5个EXECUTE_FAILED。
请注意,从12c(数据库和驱动程序)开始,您可以获得批处理中每个元素的更新计数。当您在批处理中执行更新时,这会更有用。对于批处理中的每个元素,您可以知道更新了多少行。

hlswsv35

hlswsv353#

我用这种方法处理了这个错误,希望能有所帮助。我们通过调用getUpdateCounts得到一个异常中的整数数组(-3值表示查询失败,或者您可以通过Statement.EXECUTE_FAILED来检查)。因此,您可以循环遍历数组,找出查询失败的索引,并将该索引Map到您的查询列表。这样,您就可以找出哪些查询失败了。

db.withTransaction {
            try {
                db.withBatch () { stmt ->
                    finalQueries.each {
                        log.debug("Query : ${it}")
                        try {
                            stmt.addBatch(it);
                        } catch (Exception e) {
                            log.error("Error while executing query", e.getMessage());
                            errors.add(e.getMessage());
                        }
                    }
                }
            } catch (Exception e) {
                log.error("Error in query ", e.getMessage())
                def res = e.getUpdateCounts();
                res.each {
                    if(it == Statement.EXECUTE_FAILED) {
                        errors.add("Error in query : " + finalQueries[it]);
                    }
                }
                errors.add(e.getMessage());
            }

finalQueries包含所有查询。

[
    "set sql_safe_updates=0;",
    "Update users set ACCOUNTLOCKE = 0 where userkey = 27;",
    "Update users set asd = 0 where userkey = 28;",
    "Update users set city = 'solapur' where userkey = 29;",
    "set sql_safe_updates=1;" 
]

相关问题