EJB JPA CMT — ошибка сброса в большом наборе данных

У меня есть веб-приложение JBoss 6.3 EAP, JPA 2.0, EJB 3.1, CMT JTA. БД - это MSSQL2008R2, с использованием драйвера MS JDBC и спящего режима 4.2.14 под капотом.

У меня есть метод, который выглядит примерно так, чтобы дублировать миллион сущностей Prices:

public void doStuff(Date newDate)
{
    List<Prices> prices = dao.getPrices(); //<< 1000000+ prices
    for (Prices price : prices)
    {
        Prices copy = price.clone();
        copy.setDate(newDate);
        entityManager.persist(copy);
        if (newDate.before(someDate))
        {
            price.setDate(someDate);
            entityManager.merge(price);
        }
    }
}

Я установил тайм-аут координатора JBoss EJB на час, чтобы он работал. Я увеличил размер кучи до -Xmx 3G после того, как в первый раз закончилась память.

Код начинается в 1:24, завершается в 1:36, затем в 2:24 происходит сбой с ошибкой транзакции и откат. Трассировка стека говорит, что это во время сброса.

 at org.hibernate.ejb.AbstractEntityManagerImpl$CallbackExceptionMapperImpl.mapManagedFlushFailure(AbstractEntityManagerImpl.java:1510) [hibernate-e
ntitymanager-4.2.14.SP1-redhat-1.jar:4.2.14.SP1-redhat-1]

Я вижу, что если я разобью миллион на куски по 10000 и сброшу после каждого, то в течение часа он даже не приблизится к миллиону. Так что промывка явно затратная задача. Но я предполагаю, что он начинает неявно сбрасываться во время фиксации JTA после перехвата.

Должен ли я просто увеличить время ожидания и повторить попытку? Это база данных DEV, используемая несколькими другими, и мой код, кажется, блокирует таблицу цен, делая ее невозможной для запроса из MSSQL SMSS, поэтому я не хочу, чтобы это было то, что я хочу, чтобы работать бесконечно. Но это просто вопрос необходимости больше времени?

Начало трассировки стека:

02:24:45,157 WARN  [com.arjuna.ats.arjuna] (Transaction Reaper) ARJUNA012117: TransactionReaper::check timeout for TX 0:ffff0a14021f:3d218bb8:56009132:22 in state  RUN
02:24:45,169 WARN  [com.arjuna.ats.arjuna] (Transaction Reaper Worker 0) ARJUNA012095: Abort of action id 0:ffff0a14021f:3d218bb8:56009132:22 invoked while multiple threads active within it.
02:24:45,169 WARN  [com.arjuna.ats.arjuna] (Transaction Reaper Worker 0) ARJUNA012108: CheckedAction::check - atomic action 0:ffff0a14021f:3d218bb8:56009132:22 aborting with 1 threads active!
02:24:45,667 WARN  [com.arjuna.ats.arjuna] (Transaction Reaper) ARJUNA012117: TransactionReaper::check timeout for TX 0:ffff0a14021f:3d218bb8:56009132:22 in state  CANCEL
02:24:46,209 WARN  [com.arjuna.ats.arjuna] (Transaction Reaper) ARJUNA012117: TransactionReaper::check timeout for TX 0:ffff0a14021f:3d218bb8:56009132:22 in state  CANCEL_INTERRUPTED
02:24:46,210 WARN  [com.arjuna.ats.arjuna] (Transaction Reaper) ARJUNA012120: TransactionReaper::check worker Thread[Transaction Reaper Worker 0,5,main] not responding to interrupt when cancelling TX 0:ffff0a14021f:3d218bb8:56009132:22 -- worker marked as zombie and TX scheduled for mark-as-rollback
02:24:46,210 WARN  [com.arjuna.ats.arjuna] (Transaction Reaper) ARJUNA012110: TransactionReaper::check successfuly marked TX 0:ffff0a14021f:3d218bb8:56009132:22 as rollback only
02:25:07,968 WARN  [org.hibernate.engine.jdbc.spi.SqlExceptionHelper] (http-/0.0.0.0:8080-1) SQL Error: 0, SQLState: null
02:25:07,968 ERROR [org.hibernate.engine.jdbc.spi.SqlExceptionHelper] (http-/0.0.0.0:8080-1) Transaction cannot proceed STATUS_ROLLEDBACK
02:25:08,085 WARN  [com.arjuna.ats.arjuna] (http-/0.0.0.0:8080-1) ARJUNA012125: TwoPhaseCoordinator.beforeCompletion - failed for SynchronizationImple< 0:ffff0a14021f:3d218bb8:56009132:24, org.hibernate.engine.transaction.synchronization.internal.RegisteredSynchronization@2d633a18 >: javax.persistence.PersistenceException: org.hibernate.exception.GenericJDBCException: could not prepare statement

person djb    schedule 22.09.2015    source источник


Ответы (1)


Ну, я переписал его как SQL и использовал 2 вызова entityManager.createNativeQuery вместо программного JPA, и это закончилось примерно через 30 секунд.

Итак, урок таков: не беспокойтесь о JPA для больших наборов данных. Разработайте решение на SQL, а затем используйте для этого прямое соединение JDBC.

person djb    schedule 24.09.2015