2015-09-22 4 views
0

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

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

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, поэтому я не хочу запускать ее неограниченно долго. Но разве это вопрос, требующий большего времени?

Начало StackTrace:

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[email protected]2d633a18 >: javax.persistence.PersistenceException: org.hibernate.exception.GenericJDBCException: could not prepare statement 

ответ

0

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

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

Смежные вопросы