29.09.2008, 09:23 | #1 |
Участник
|
Ошибка с транзакциями!
Доброе время суток коллеги!
Свалилась на мою голову напасть не пойму почему не работает один отчет. Жалуется на непарность транзакций. Недели 3 назад все работало. Вроде ничего не менял. Нашел участок кода, который больше всего подходит к ошибке транзакций. X++: container run() { int ret, nullret; ; this.initNeedsCalc(); try { ttsbegin; [ret, nullret] = this.createNeeds(); ttscommit; } catch (Exception::Deadlock) { retry; } catch (Exception::Error) { error(strfmt("График %1 не обработан", deliverySchedule.PurchRequestId ) ); } return [ret, nullret]; } возникнет ошибка, то выход из исключения будет без отмены транзакции? Эта ошибка возникает периодически, но сообщения типа "График 001 не обработан" не появляется. |
|
29.09.2008, 09:39 | #2 |
Участник
|
Следите за appl.ttsLevel() (или в отладчике за значением tts в статусной строке).
На входе и на выходе из процедуры его вызов должен возвращать одинаковое значение. Если значение счетчика увеличивается, значит где-то во внутренних вызовах есть лишний ttsbegin.
__________________
Axapta v.3.0 sp5 kr2 |
|
29.09.2008, 09:53 | #3 |
Участник
|
AndyD
Так в отладчике редко возникает, и она не всегда возникает в рабочем режиме. Думаю может это Exception:eadlock возникает? (У нас кстати частые проблемы с блокировками в последнее время) А при возникновении исключения соответственно не выдается никакого сообщения, но при этом ошибка непарности ttsbegin ttscommit высвечивается? Будет ли работать ttsabort по ветке условия Exception:eadlock? |
|
29.09.2008, 12:15 | #4 |
Участник
|
Для начала, строим тестовый Job для проверки собственных идей. У меня Ax2.5, поэтому логика может несколько отличаться в старших версиях.
X++: static void test_TryCatchTransaction(Args _args) { ; try { ttsbegin; ttsbegin; throw exception::Deadlock; ttscommit; ttscommit; } catch (exception::Break) { info('exception::Break'); } catch (exception::DDEerror) { info('exception::DDEerror'); } catch (exception::Deadlock) { info('exception::Deadlock'); } catch (exception::Error) { info('exception::Error'); } catch (exception::Info) { info('exception::Info'); } catch (exception::Internal) { info('exception::Internal'); } catch (exception::Sequence) { info('exception::Sequence'); } catch (exception::Warning) { info('exception::Warning'); } info(strFmt("Количество вложенных транзакций = %1", appl.ttsLevel())); } Однако возникают следующие вопросы: Находятся ли команды по началу и завершению транзакции в одном методе? Внутри одного Try..Catch? По крайней мере, вызов методов по началу и завершению транзакции? Не возникает ли ситуации, когда после выброса на верхний уровень транзакции команда по завершению транзакции оказывается вне обработчика Try..Catch? Т.е. надо отследить вот такие программные конструкции X++: static void test_TryCatchTransaction(Args _args) { ; try { ttsbegin; throw exception::Error; } catch (exception::Error) { info('exception::Error'); } // Вот здесь возникнет ошибка ttscommit; } |
|
29.09.2008, 14:14 | #5 |
Участник
|
В методе createNeeds()
Не используются ttsbegin ttscommit. Вот блин ну где же может быть ошибка |
|
29.09.2008, 14:29 | #6 |
Ищущий знания...
|
Цитата:
с этими непарными транзакциями вечно морока, пока найдешь откуда ползет поседеешь
__________________
"Страх перед возможностью ошибки не должен отвращать нас от поисков истины." (с) С Уважением, Елизаров Артем |
|
29.09.2008, 14:57 | #7 |
Участник
|
Можно попробовать отловить ошибку, используя методы Application.ttsNotifyBegin() и Application.ttsNotifyCommit(). К примеру, можно дописать в них код, который, если текущий пользователь такой-то (чтоб срабатывало не у всех), записывал в какой-нить лог информацию о том, откуда вызван метод (см. Global::callStack2Infolog()) и какой текущий уровень транзакций на момент вызова метода, а в ttsNotifyCommit() сделать дополнительную проверку на то, что до вызова этого метода appl.ttsLevel() уже равен нулю, и поставить точку останова на этой ветке кода, чтобы отловить ее в отладчике. Тогда можно будет, по крайней мере, до вылета ошибки посмотреть, где именно она возникает, а по созданному логу отследить момент, когда ttsbegin/ttscommit разбалансируются (ведь предположительно они должны вызываться в рамках одного метода). Ну и погонять ваш отчет под "нужным" пользователем до момента возникновения ошибки.
|
|
|
За это сообщение автора поблагодарили: lev (1), demon46 (1). |
29.09.2008, 15:06 | #8 |
Участник
|
gl00mie Благодарю. Дельный совет!
|
|
29.09.2008, 16:11 | #9 |
Участник
|
gl00mie
Какая-то фигня отображается. Вот что я дописал. X++: void ttsNotifyCommit() { str User; ; User = CurUserid(); if (User == 'dgol' || User == 'ipas' || User == 'robo') { info("LEVEL "+Num2Str(appl.ttsLevel(),1,0,1,0)); Global::callStack2infolog(); } if (appl.ttsLevel()==0) info("Error"); this.inventUpdateTTSControl().ttsNotifyCommit(); this.numberSeqGlobal().ttsNotifyCommit(); } а стек вызова всегда "\Classes\Application\ttsNotifyBegin 9" |
|
29.09.2008, 16:56 | #10 |
Участник
|
Мда, все оказалось не так просто... По ходу ttsNotifyBegin()/ttsNotifyCommit() вызываются только после соотв. начала/завершения транзакции и лишь тогда, когда ttslevel < 1, т.е. для вложенных ttsbegin/ttscommit этим методы уже не вызываются А что касается стека вызовов, то у меня, к примеру, получается вот что:
здесь в методе SysSetupFormRun.task() в указанной 49-й строке вызывается super() |
|
29.09.2008, 17:08 | #11 |
Участник
|
Коллега высказал мнение, что ошибка с не балансирующими транзакциями может еще возникать, если внутри транзакции открывается какая-то форма. Это можно проверить, поставив заглушку в \Classes\SysSetupFormRun\init, проверять там текущий appl.ttsLevel() и, если он ненулевой, писать тот же стэк вызовов куда-нибудь...
|
|
|
За это сообщение автора поблагодарили: evv (1). |
29.09.2008, 18:43 | #12 |
Участник
|
|
|
06.10.2008, 09:15 | #13 |
Участник
|
А текущий уровень транзакций TTS - 1. (в диалоге, когда возникает ошибка транзакций) Это до выполнения операции с транзакциями или уже после появления ошибки?
И вобще отчет разделен на 2 части. В одной формируются журналы, а во второй происходит рассылка почтовых сообщений информирующих о создании журналов. Так вот сегодня у меня ошибка вывалилась во второй части, где нет никаких транзакционных скобок. Там просто выбираются номера журналов из таблицы, и с помощью EXCEL формируются вложенные файлы, а затем при помощи Postie отправляются письма. Может быть это связано с совместным доступом к журналу? |
|
06.10.2008, 13:19 | #14 |
Участник
|
Цитата:
По идее вариант gl00mie помогает поймать баг в момент возникновения. А когда вылезла форма о том, что тарнзакции не балансируют - то как говорится уже "поздняк метаться". |
|
Теги |
транзакции |
|
Опции темы | Поиск в этой теме |
Опции просмотра | |
|