| Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате |
| Форум программистов > 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:
похоже этот 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К ---- млин, вот трабла вылезла |
| Автор: lando1 12.2.2009, 22:03 |
| а обработка данных у вас идет последовательно? у меня такое было иногда когда много одновременных запросов через entity manager одного класса. Я ее решил путем выстраивания запросов в очередь с помощью ReentrantLock. |
| Автор: 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 | ||
так опасно.. если кто-то во время записи половины придёт запрашивать какое-то поле, то база данных вернёт уже существующие поля. "хохма" будет, если что-то не удасться. наш трансактион "откатит" состояние и если теперь етот кто-то опять придёт за полем, то хана.. его нет не, нада так, или всё, или ничего.. другого не дано.. |
| Автор: ecologist 15.2.2009, 21:47 |
| А может проще сделать прямую запись в базу ? Причем в синтаксис SQL для некоторых баз позволяет делать сразу несколько вставок. Думаю, что прямое обращение будет быстрее. Скорее всего такого рода задачи - это заливка новых данных, которые будут исползованы в реальной работе позже. Можно и в обход EJB такое сделать. |
| Автор: DimW 16.2.2009, 10:47 |
polosatij, вам не кажется что эта задача не совсем для сервера приложений. поскольку: нельзя пересмотреть решение и воспользоваться средствами ORACLE для работы с XML? если возникнут вопросы то обрашайтесь в соответствующюу ветку. |
| Автор: fixxer 16.2.2009, 11:25 | ||
+1 |
| Автор: polosatij 16.2.2009, 21:21 | ||||
ты прав.. но принимая тот факт, что в 199% из 200 это всё же задача для сервера приложений.. а один раз в месяц - два, нет, т.к. нужно будет заливать большие данные, то пришлось написать всё под общую структуру уже имеющегося приложения, т.к. в нём уже есть свои Entity и прочие, мне пришлось всё расширить..
у нас бегает postgreSQL.. я никогда не писал приложения "XML большой -> импорт PostgreSQL"... задача также -> не привязываться к базе данных, посему бегают EJB. боюсь слишком тяжёлая логика, т.к. саму логику я писал около одного месяца.. там данные приходят разных типов.. хм.. а неужели можно?!.. ех-ха.. пошёл за ключами на трактор.. сейчас буду вспахивать.. |
| Автор: polosatij 17.2.2009, 00:53 | ||
нельзя писать на прямую, это запрещено кодексом фирмы.. иначе я давно бы уже "захимичил".. |
| Автор: ecologist 17.2.2009, 08:19 |
Ну тогда пусть изобретатель такого кодекса и мучается. Ты попробовал несколько вариантов - не очень получается. Никто не сможет заставить черепаху бежать быстрее зайца. Тут тоже самое. Если начальству важен кодекс - пусть оно с ним и ... имеет сексуальные отношения. |
| Автор: polosatij 17.2.2009, 14:44 | ||
ну.. а что делать?!.. моё дело маленькое, чтоб бегали мои два компонента на кодексах фирмы кстати, я нашёл решение: часть моего приложения бегает outside of session bean, посему мне надо было применять joinTransaction() + поднять время TransactionTimeout. я вчера неимоверно подпрыгнул на стуле, когда моё приложение не упало через 25 минут =) сейчас буду эксперементировать дальше |
| Автор: polosatij 17.2.2009, 18:54 |
поекспериментировал с Cashe-ем hibernate, добился результата импорта до 35 минут с 1.5 часа всем пасиба |