1

我正在调用一种方法,它对 DB2 数据库中的单个数据集执行 SQL UPDATE。从 ActiveMQ 队列接收到消息后,该方法在不同的线程中自动调用。它在 2 秒内被调用了 5 次,但是因为第一次调用在数据集上设置了 WRITE-Lock,所以接下来的 3 次调用必须等待。在第一次调用完成更新后,第二次调用不会执行更新,而是会运行一个新的方法调用(行中的第 5 个调用)。问题是,中间的三个调用没有识别出 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 更新调用将按调用顺序执行。

4

1 回答 1

1

我们以前遇到过同样的问题,我们遵循这个:

问题(摘要)

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

原因

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

解决问题

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

这里是原始技术说明

于 2019-01-23T09:24:55.850 回答