java - 在不同线程中调用SQL更新后如何修复 'SQLException SQL0913'

标签 java db2 db2-400 jboss-eap-6 jpa

我正在调用一个方法,该方法对 DB2 数据库中的单个数据集执行 SQL 更新。从ActiveMQ队列接收到消息后,该方法会在不同的线程中自动调用。它在 2 秒内被调用 5 次,但由于第一个调用在数据集上设置了 WRITE-Lock,所以接下来的 3 个调用必须等待。第一次调用完成更新后,第二次调用不会执行更新,而是执行新的方法调用(行中的第五次调用)。问题是,中间的三个调用无法识别 WRITE-Lock 已释放,并且在 1 分钟超时后抛出 SQLException 错误 SQL0913。

Caused by: java.sql.SQLException: [SQL0913] Zeile oder Objekt PR1BAFPU5 der Art *FILE in DAKDTA wird verwendet. Ursache  . . . . :  Das angeforderte Objekt PR1BAFPU5 der Art *FILE in der Bibliothek DAKDTA wird gerade von einem anderen Anwendungsprozess verwendet, oder eine Zeile im Objekt wird von einem anderen Anwendungsprozess oder einem anderen Cursor in diesem Anwendungsprozess verwendet. Fehlerbeseitigung:  Die vorherigen Nachrichten im Jobprotokoll aufrufen (Befehl DSPJOBLOG) oder im interaktiven SQL F10 (Nachrichten im Jobprotokoll anzeigen) in dieser Anzeige drücken, um zu bestimmen, ob es sich um eine Wartezeitüberschreitung für eine Objekt- oder Satzsperre handelt. Einen der folgenden Schritte durchführen: -- Wird ein Objekt durch einen anderen Anwendungsprozess gesperrt, die SQL-Anweisung wiederholen, wenn das Objekt nicht verwendet wird. Mit dem Befehl WRKOBJLCK (Mit Objektsperren arbeiten) kann festgestellt werden, von wem das Objekt gerade verwendet wird. -- Ist das Objekt ein Schema und wurde versucht, in diesem Schema eine Tabelle, eine Sicht oder einen Index unter COMMIT-Steuerung zu erstellen, wird möglicherweise für dieses Schema gerade eine Operation zum "Sichern im aktiven Zustand" von einem anderen Job im System durchgeführt. Ist die Operation zum "Sichern im aktiven Zustand" abgeschlossen, die Anforderung wiederholen. -- Wird ein Satz durch einen anderen Anwendungsprozess gesperrt, die SQL-Anweisung wiederholen, wenn der Satz nicht verwendet wird. Mit dem Befehl DSPRCDLCK (Satzsperren anzeigen)kann festgestellt werden, von wem der Satz gerade verwendet wird. -- Wird der Satz von einem anderen Cursor in demselben Anwendungsprozess gesperrt, muss eine Anweisung COMMIT, ROLLBACK oder eine andere Anweisung FETCH für den Cursor ausgegeben werden, der die Sperre verursacht, bevor diese SQL-Anweisung ausgegeben wird. Tritt dieser Fehler häufig auf, mit dem Befehl CHGPF (Physische Datei ändern), CHGLF (Logische Datei ändern) oder OVRDBF (Datenbankdatei überschreiben) die Wartezeitüberschreitung für das Objekt oder den Satz ändern. 
        at com.ibm.as400.access.JDError.createSQLExceptionSubClass(JDError.java:860) [jt400-jdbc4-7.8.jar:JTOpen 7.8] 
        at com.ibm.as400.access.JDError.throwSQLException(JDError.java:692) [jt400-jdbc4-7.8.jar:JTOpen 7.8] 
        at com.ibm.as400.access.JDError.throwSQLException(JDError.java:662) [jt400-jdbc4-7.8.jar:JTOpen 7.8] 
        at com.ibm.as400.access.AS400JDBCStatement.commonExecute(AS400JDBCStatement.java:1025) [jt400-jdbc4-7.8.jar:JTOpen 7.8] 
        at com.ibm.as400.access.AS400JDBCPreparedStatement.executeUpdate(AS400JDBCPreparedStatement.java:1649) [jt400-jdbc4-7.8.jar:JTOpen 7.8] 
        at org.jboss.jca.adapters.jdbc.WrappedPreparedStatement.executeUpdate(WrappedPreparedStatement.java:493) 
        at org.hibernate.engine.jdbc.internal.ResultSetReturnImpl.executeUpdate(ResultSetReturnImpl.java:186) [hibernate-core-4.2.27.Final-redhat-1.jar:4.2.27.Final-redhat-1] 
        ... 143 more 

数据库是IBM DB2数据库(版本7.2),我的程序运行在JBoss EAP-6.4上。从日志来看,第一个调用似乎需要几秒钟才能执行,接下来的三个调用正在等待第一个调用。但是第一个执行完成后,接下来的三个调用就没有继续进行。

public void updateBerthTimeConflictFlag4BerthArrival(boolean conflict, String berthArrivalId) { 
                Query updateQuery = em.createNativeQuery("update PR1BERTHARRIVAL_FLZ set berthTimeConflict = :conflict where id = :id"); 
                updateQuery.setParameter("conflict", conflict ? 1 : 0); 
                updateQuery.setParameter("id", berthArrivalId); 
                updateQuery.executeUpdate(); 
        } 

我希望在第一个调用完成后,接下来的三个 SQL 更新调用将按照调用顺序执行。

最佳答案

我们以前也遇到过同样的问题,我们遵循以下步骤:

问题(摘要)

当应用程序使用 JDBC 从表中读取多条记录并使用 BMP 实体 bean 删除表中的记录时,出现错误“java.sql.SQLException: [SQL0913] Row or object F55500 in type *FILE”发生“正在使用”。

原因

异常表明行或对象正在使用中。

解决问题

在读取多条记录的JDBC程序中,需要保证所有连接都关闭,以便释放所有资源。 如果没有直接的方法来释放连接,重新启动数据库将删除所有打开的连接,但如果没有其他替代方法来释放连接,这将是最后的措施。 不使用 JDBC 程序,而是创建一个单独的 session bean 来包含对数据库的查询。 session Bean 的事务设置应为 RequiresNew。 SQL 语句现在在新的单独事务中运行。一旦该方法完成运行,事务就会结束​​,并且表将被释放以供 BMP 实体 bean 用来删除。

这里是原文technote

关于java - 在不同线程中调用SQL更新后如何修复 'SQLException SQL0913',我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54305375/

相关文章:

database - DB2 实例是否与数据库实例相同?

sql - Iseries SQL 更新

db2 - 我们如何查看DB2过程以及如何执行DB2过程并仅使用DB2看到过程的输出

sql - 如何消除 DB2400 或任何 SQL 中 JSON_ARRAYAGG 中的重复行?

Java进程构建器: Resultant Process Hangs

java - Android fragment NullPointerException 错误

java - 如何使 EJB 计时器持久化为 false

java - DB2 错误 SQLCODE=-103,SQLSTATE=42604

java - 错误: “Method getText() must be called from the UI thread, currently inferred thread is worker.”

mysql - 从一个数据源选择数据并将其存储在另一个数据源中