Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Java EE (J2EE) и Spring > @EJB, 50.000 записей


Автор: polosatij 12.2.2009, 21:07
ко мне в систему приходит XML File 4 Giga, из него я достаю определённые Entity и сохраняю в базу данных.. система такая: всё реализовано как "сервис" -> @EJB Stateless Bean, а именно:

MBean --> @EJB Stateless Bean --> Strategy (обрабатывает XML и по очереди сохраняет Entity)..
                       (тут стартует транзакция)

операция может длится от 5 секунд до 24 часов, в зависимости от приходящего файла.

после примерно 15 минут работы выбрасывается Exception: 

Код

2009-02-12 15:07:40,740 DEBUG [mbean.AIXMTest] javax.persistence.TransactionRequiredException: EntityManager must be access within a transaction
javax.ejb.EJBException: javax.persistence.TransactionRequiredException: EntityManager must be access within a transaction
        at org.jboss.ejb3.tx.Ejb3TxPolicy.handleExceptionInOurTx(Ejb3TxPolicy.java:69)
        at org.jboss.aspects.tx.TxPolicy.invokeInOurTx(TxPolicy.java:83)
        at org.jboss.aspects.tx.TxInterceptor$Required.invoke(TxInterceptor.java:191)
        at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:101)
        at org.jboss.aspects.tx.TxPropagationInterceptor.invoke(TxPropagationInterceptor.java:76)
        at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:101)
        at org.jboss.ejb3.stateless.StatelessInstanceInterceptor.invoke(StatelessInstanceInterceptor.java:62)
        at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:101)
        at org.jboss.aspects.security.AuthenticationInterceptor.invoke(AuthenticationInterceptor.java:77)
        at org.jboss.ejb3.security.Ejb3AuthenticationInterceptor.invoke(Ejb3AuthenticationInterceptor.java:102)
        at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:101)
        at org.jboss.ejb3.ENCPropagationInterceptor.invoke(ENCPropagationInterceptor.java:47)
        at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:101)
        at org.jboss.ejb3.asynchronous.AsynchronousInterceptor.invoke(AsynchronousInterceptor.java:106)
        at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:101)
        at org.jboss.ejb3.stateless.StatelessContainer.localInvoke(StatelessContainer.java:211)
        at org.jboss.ejb3.stateless.StatelessLocalProxy.invoke(StatelessLocalProxy.java:79)
        at $Proxy688.parseFromFileSystem(Unknown Source)
        at de.comsoft.cadas_ims.mbean.AIXMTest.parse(AIXMTest.java:163)
        at de.comsoft.cadas_ims.mbean.AIXMTest.testFirstSnapshotXMLInvalide(AIXMTest.java:150)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
        at java.lang.reflect.Method.invoke(Method.java:585)


похоже этот Exception говорит о том, что сессия была закрыта. возможные предположение: DeadLock распознование, TimeOut Transaction-a..

на данный момент есть три варианта решения проблемы, если это действительно Transaction Timeout..  хотелось бы сказать о том, что ставить в базу данных поля о том, что поле новое или нет не получится.. нужно решение: ЛИБО ВСЁ ЛИБО НИЧЕГО..

1). если пройдёт такой вариант: ставим SessionTimeout = 1 day, write-lock, without read-lock
// это пожалуй самый простой вариант если он пройдёт.. однако он заблокирует хорошенько систему на запись.. вроде как сейчас это не кретично.. но получится ли сделать так?

2). ставлю batch size в hibernate на 10, 100 или 1000. при этом будет застартована новая сессия.. работаю с tmp таблицой.. потом беру настоящую таблицу и tmp и делаю некий merge с помощью PSQL в трансакции
// это пожалуй сейчас наиболее подходящий вариант, если не получится вариант (1). положительные стороны, PSQL работает быстро и поставит lock на гораздо меньший промежуток нежели вариант (1)

3). делаем копию нескольких таблиц учавствующих в операции.. делаем изменения в  копиях.. делаем switch с таблицы такой-то на таблицу такую-то (переписываем полностью)
// что мне тут не нравится, это объём данных

4). про этот вариант сразу можно забыть: добавить в таблицах новое поле -> номер, определяющее версию и после окончания нужно стереть --i версию. трабла: не только insert нового поля, но и изменение поля --i, а именно времени (фуф, надеюсь понятно)

5). пишу всю эту бойду в отдельный файл и потом натравливаю python или что-нибудь в postgresql прочитать этот файл и закомитить с некой логикой ( на каждое поле должно будет вызваться некая логика)
// не слишком ли много вызовов? а может бд за меня это сама сделает и не надо никакого python-а, например?

----

примерный объём данных 100.000 - 1.000.000 полей в среднем на 5-7 стрингов по 15 букв в среднем + 1 бинарное поле не более 0,1К

----

млин, вот трабла вылезла  smile  smile 

Автор: lando1 12.2.2009, 22:03
а обработка данных у вас идет последовательно?
у меня такое было иногда когда много одновременных запросов через entity manager одного класса. Я ее решил путем выстраивания запросов в очередь с помощью ReentrantLock.

Автор: polosatij 12.2.2009, 22:09
Цитата(lando1 @  12.2.2009,  21:03 Найти цитируемый пост)
а обработка данных у вас идет последовательно?


да.. шаг за шагом..


Цитата(lando1 @  12.2.2009,  21:03 Найти цитируемый пост)
у меня такое было иногда когда много одновременных запросов через entity manager одного класса. Я ее решил путем выстраивания запросов в очередь с помощью ReentrantLock. 


ты бы не мог описать по подробнее/ запостить код, если есть? заранее БОЛЬШОЕ пасиба  smile 

Автор: polosatij 13.2.2009, 22:41

поигрался с

@TransactionAttribute
ReentrantLock // хотя по мне, это вообще сюда  не относится
@TransactionTimeout(999999)

в общем, ерунда это всё.. решил взять вариант (2) и писать в tmp таблицы, а потом пройтись PL/SQL.. и хотя мне очень хочется отказаться от EJB на этом уровне, к сожалению я сделать это не могу.. 

Автор: necromancer 13.2.2009, 23:06
=) я бы попробовал решать эту задачу попроще =)
берем некий айдишник и инкрементально присваиваем каждой записи =))) если что то не так удаляем в дипазоне старта и тсопа. что бы в случае чего не потерять эти айдишники и результат операции храним строчку вида:
старт Id стоп Id action(not finish) =))))

Автор: polosatij 15.2.2009, 14:46
Цитата(necromancer @  13.2.2009,  22:06 Найти цитируемый пост)
=) я бы попробовал решать эту задачу попроще =)
берем некий айдишник и инкрементально присваиваем каждой записи =))) если что то не так удаляем в дипазоне старта и тсопа. что бы в случае чего не потерять эти айдишники и результат операции храним строчку вида:
старт Id стоп Id action(not finish) =)))) 


так опасно.. если кто-то во время записи половины придёт запрашивать какое-то поле, то база данных вернёт уже существующие поля. "хохма" будет, если что-то не удасться. наш трансактион "откатит" состояние и если теперь етот кто-то опять придёт за полем, то хана.. его нет  smile 

не, нада так, или всё, или ничего.. другого не дано.. smile

Автор: ecologist 15.2.2009, 21:47
А может проще сделать прямую запись в базу ? Причем в синтаксис SQL для некоторых баз позволяет делать сразу несколько вставок.
Думаю, что прямое обращение будет быстрее. Скорее всего такого рода задачи - это заливка новых данных, которые будут исползованы в реальной работе позже. Можно и в обход EJB такое сделать.

Автор: DimW 16.2.2009, 10:47
Цитата(polosatij @  12.2.2009,  21:07 Найти цитируемый пост)
XML File 4 Giga

Цитата(polosatij @  12.2.2009,  21:07 Найти цитируемый пост)
операция может длится от 5 секунд до 24 часов

polosatij, вам не кажется что эта задача не совсем для сервера приложений.

поскольку: 
Цитата(polosatij @  13.2.2009,  22:41 Найти цитируемый пост)
а потом пройтись PL/SQL

нельзя пересмотреть решение и воспользоваться средствами ORACLE для работы с XML?
если возникнут вопросы то обрашайтесь в соответствующюу ветку.

Автор: fixxer 16.2.2009, 11:25
Цитата(DimW @ 16.2.2009,  10:47)
Цитата(polosatij @  12.2.2009,  21:07 Найти цитируемый пост)
XML File 4 Giga

Цитата(polosatij @  12.2.2009,  21:07 Найти цитируемый пост)
операция может длится от 5 секунд до 24 часов

polosatij, вам не кажется что эта задача не совсем для сервера приложений.

поскольку: 
Цитата(polosatij @  13.2.2009,  22:41 Найти цитируемый пост)
а потом пройтись PL/SQL

нельзя пересмотреть решение и воспользоваться средствами ORACLE для работы с XML?
если возникнут вопросы то обрашайтесь в соответствующюу ветку.

+1

Автор: polosatij 16.2.2009, 21:21
Цитата(DimW @  16.2.2009,  09:47 Найти цитируемый пост)
polosatij, вам не кажется что эта задача не совсем для сервера приложений.


ты прав.. но принимая тот факт, что в 199% из 200 это всё же задача для сервера приложений.. а один раз в месяц - два, нет, т.к. нужно будет заливать большие данные, то пришлось написать всё под общую структуру уже имеющегося приложения, т.к. в нём уже есть свои Entity и прочие, мне пришлось всё расширить..



Цитата(DimW @  16.2.2009,  09:47 Найти цитируемый пост)
нельзя пересмотреть решение и воспользоваться средствами ORACLE для работы с XML?
если возникнут вопросы то обрашайтесь в соответствующюу ветку. 



у нас бегает postgreSQL..

я никогда не писал приложения "XML большой -> импорт PostgreSQL"...  задача также -> не привязываться к базе данных, посему бегают EJB.
боюсь слишком тяжёлая логика, т.к. саму логику я писал около одного месяца.. там данные приходят разных типов.. хм.. а неужели можно?!..  smile 

ех-ха.. пошёл за ключами на трактор.. сейчас буду вспахивать..  smile 


Автор: polosatij 17.2.2009, 00:53
Цитата(ecologist @  15.2.2009,  20:47 Найти цитируемый пост)
А может проще сделать прямую запись в базу ? Причем в синтаксис SQL для некоторых баз позволяет делать сразу несколько вставок.


нельзя писать на прямую, это запрещено кодексом фирмы.. иначе я давно бы уже "захимичил"..  smile 

Автор: ecologist 17.2.2009, 08:19
Цитата(polosatij @  17.2.2009,  00:53 Найти цитируемый пост)
нельзя писать на прямую, это запрещено кодексом фирмы

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

Автор: polosatij 17.2.2009, 14:44
Цитата(ecologist @  17.2.2009,  07:19 Найти цитируемый пост)
Ну тогда пусть изобретатель такого кодекса и мучается. Ты попробовал несколько вариантов - не очень получается. Никто не сможет заставить черепаху бежать быстрее зайца. Тут тоже самое. Если начальству важен кодекс - пусть оно с ним и ... имеет сексуальные отношения.


ну.. а что делать?!.. моё дело маленькое, чтоб бегали мои два компонента на кодексах фирмы smile

кстати, я нашёл решение: часть моего приложения бегает outside of session bean, посему мне надо было применять joinTransaction() + поднять время TransactionTimeout. я вчера неимоверно подпрыгнул на стуле, когда моё приложение не упало через 25 минут =)

сейчас буду эксперементировать дальше smile

Автор: polosatij 17.2.2009, 18:54

поекспериментировал с Cashe-ем hibernate, добился результата импорта до 35 минут с 1.5 часа  smile чувствую, что во многих местах надо ещё подточить напильником и, возможно, время снизится ещё вдвое/ трое  smile крута, это значит, за ночь как раз успеет импортировать полноценный файл  smile 

всем пасиба  smile 

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)