Как исправить 'SQLException SQL0913' после вызова обновления SQL в разных потоках - PullRequest
0 голосов
/ 22 января 2019

Я вызываю метод, который выполняет SQL UPDATE для одного набора данных в базе данных DB2. Метод вызывается автоматически в разных потоках после получения сообщения из очереди ActiveMQ. Он вызывается 5 раз за 2 секунды, но поскольку первый вызов устанавливает WRITE-Lock для набора данных, следующие 3 вызова должны ждать. После того как первый вызов завершает обновление, второй вызов не выполняет обновление, вместо этого выполняется новый вызов метода (5-й вызов в строке). Проблема в том, что три вызова между ними не распознают, что WRITE-Lock был снят, и выдают SQLException с ошибкой SQL0913 по истечении времени ожидания 1 минута.

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 будут выполнены в порядке вызова.

1 Ответ

0 голосов
/ 23 января 2019

У нас была такая же проблема несколько раз назад, и мы следуем ей:

Проблема (абстрактная)

Когда приложение читает несколько записей с использованием JDBC изтаблица и использует объектный компонент BMP для удаления записей из таблицы, возникает ошибка «java.sql.SQLException: [SQL0913] Строка или объект F55500 в типе * FILE используется».

Причина

Исключение указывает, что строки или объекты используются.

Решение проблемы

В программе JDBC, которая читает числозаписей, вы должны убедиться, что все соединения закрыты, чтобы освободить все ресурсы.Если нет прямого способа освободить соединение, перезапуск базы данных удалит все открытые соединения, но это будет последней мерой, если нет другой альтернативы для освобождения соединений.Вместо использования программы JDBC создайте отдельный сессионный компонент для хранения запроса к базе данных.Сессионный компонент должен иметь значение транзакции Требуется новый .Оператор SQL теперь выполняется в новой отдельной транзакции.Как только метод завершил выполнение, транзакция завершается, и таблицы освобождаются для использования объектными компонентами BMP для удаления.

Здесь оригинальный technote

...