Массовое обновление DB2 с использованием Hibernate и Multi Threading - PullRequest
0 голосов
/ 05 февраля 2019

У меня есть требование обновить более 1000000 записей в базе данных DB2.Я попытался использовать Hibernate с многопоточным приложением, обновляющим записи.Тем не менее, при этом я получаю исключение блокировки приобретения.Я чувствую, что это из-за большого количества коммитов, которые я делаю вместе с несколькими потоками.Может кто-нибудь порекомендовать лучшее решение или лучший способ сделать это.Пожалуйста, дайте мне знать, если мне нужно загрузить код, который я использую.Заранее спасибо.

//Code running multiple times with threads 
Transaction tx = null; 
tx = session.beginTransaction(); 
for(EncryptRef abc : arList) { 
String encrypted = keyUtils.encrypt(abc.getNumber()); //to encrypt some data
Object o = session.load(EncryptRef.class,new Long(abc.getId())); //primary key EncryptRef object = (EncryptRef)o; 
object.setEncryptedNumber(encrypted); //updating the row 
} 
tx.commit(); //bulk commiting the updates

Таблица содержит всего три столбца.ID | PlainText | EncryptedText

Обновление: я пробовал пакетное обновление с использованием подготовленных JDBC состояний.Однако я все еще сталкиваюсь со следующим исключением:

com.ibm.db2.jcc.am.BatchUpdateException: [jcc] [t4] [102] [10040] [3.63.75] Ошибка пакета,Партия была отправлена, но по крайней мере одно исключение произошло с отдельным участником партии.Используйте getNextException (), чтобы получить исключения для определенных пакетных элементов.ERRORCODE = -4229, SQLSTATE = null на com.ibm.db2.jcc.am.fd.a (fd.java:407) на com.ibm.db2.jcc.am.na (n.java:386) на com.ibm.db2.jcc.am.zn.a (zn.java:4897) на com.ibm.db2.jcc.am.zn.c (zn.java:4528) на com.ibm.db2.jcc.am.zn.executeBatch (zn.java:2837) в org.npci.ThreadClass.run (ThreadClass.java:63) в java.lang.Thread.run (Thread.java:748)

Ниже приведен код, выполненный с размером пакета 50-100 записей:

String queryToUpdate = "UPDATE INST1.ENCRYPT_REF SET ENCR_NUM=? WHERE ID=?";
            PreparedStatement pstmtForUpdate = conn.prepareStatement(queryToUpdate);
            for (Map.Entry<Long,String> entry : encryptMap.entrySet()) {
                pstmtForUpdate.setString(1, entry.getValue());
                pstmtForUpdate.setLong(2, entry.getKey());
                pstmtForUpdate.addBatch();
            }
            pstmtForUpdate.executeBatch();
            conn.close();

Ответы [ 2 ]

0 голосов
/ 06 февраля 2019

Не ответ на вопрос.Используется для лучшего форматирования.

Чтобы поймать фактический SQLCODE db2, используйте следующую технику.В противном случае невозможно понять причину проблемы.

try {
  ...
} catch (SQLException ex) {
    while (ex != null) {
        if (ex instanceof com.ibm.db2.jcc.DB2Diagnosable) {
            com.ibm.db2.jcc.DB2Diagnosable db2ex = 
        (com.ibm.db2.jcc.DB2Diagnosable) ex;
            com.ibm.db2.jcc.DB2Sqlca sqlca = db2ex.getSqlca();
            if (sqlca != null) {
              System.out.println("SQLCODE: " + sqlca.getSqlCode());
              System.out.println("MESSAGE: " + sqlca.getMessage());
            } else {
            System.out.println("Error code: " + ex.getErrorCode());
            System.out.println("Error msg : " + ex.getMessage());
            }
        } else {
        System.out.println("Error code (no db2): " + ex.getErrorCode());
        System.out.println("Error msg  (no db2): " + ex.getMessage());
      }
        ex = ex.getNextException();
    }
    ...
}

Что касается поля ENCR_NUM.Возможно ли иметь фактические значения для этого столбца за пределами вашего приложения?Или такие значения могут быть сгенерированы только вашим приложением?

Нужно ли обновлять все строки таблицы или есть какое-то условие для набора идентификаторов, которые необходимо обновить?

0 голосов
/ 05 февраля 2019

Не зная ничего о структуре вашей базы данных, трудно порекомендовать конкретное решение.Если вы можете изменить базу данных, хорошей стратегией было бы разделить вашу таблицу, а затем организовать для каждого потока обновление отдельного раздела.Вместо того, чтобы несколько потоков обновляли одну большую базу данных и конфликтовали друг с другом, каждый поток эффективно обновлял бы свою собственную меньшую базу данных.

Вам также следует убедиться, что вы эффективно пакетируете обновления и не делаете их слишком часто..

Если в вашей таблице есть тонны индексов, может быть более эффективно удалить некоторые / все и перестроить после обновления, чем обновлять его на постоянной основе.Точно так же вы можете рассмотреть возможность удаления триггеров, ограничений ссылочной целостности и т. Д., А затем исправления позже.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...