|
![]() |
#1 |
MCT
|
Там смысл именно в том, что бы обновлять другим способом, делать транзацию внутри цикла, а не во вне. Собственно об этом я тогда и писал, просто нашел подтверждение своим мыслям, вот и все.
__________________
Axapta book for developer |
|
![]() |
#2 |
MCT
|
Для карсоты решения
![]() 1 С чего все началось: X++: ttsbegin; WHILE(TRUE) { SELECT FIRSTONLY current WHERE current.InvGuid == InvGUID; InvGUID = current.ParentInvGUID; SELECT FIRSTONLY parent WHERE current.ParentInvGUID == parent.InvGUID; if(parent) { //parentDistr.disableCache(); SELECT FIRSTONLY FORUPDATE parentDistr WHERE parentDistr.InvGUID == InvGUID && parentDistr.TransRecId == inventoryGuidInvoice.TransRecId //........... && parentDistr.JuridicalPersonId == inventoryGuidInvoice.JuridicalPersonId; if(parentDistr) { parentDistr.AMOUNTCUR += inventoryGuidInvoice.AmountCur;//слияние к предку //....... parentDistr.Update(); } else { parentDistr.data(InventoryGuidInvoice); parentDistr.InvGUID = parent.InvGUID; parentDistr.insert(); } } else { break; } current.clear(); } ttscommit; X++: while select { ttsbegin; select forupdate ttscommit; } X++: DO NOT: Hold database locks for longer than is necessary. DO: Limit the transaction scope by grabbing locks at the latest possible time and releasing locks as early as possible. X++: ttsBegin; while select ItemId from salesLine { select firstOnly forUpdate ItemType, ItemBuyerGroupId from inventTable where inventTable.ItemId == salesLine.ItemId; If (inventTable && (inventTable.ItemType == InventItemType::Item)) { inventTable.ItemBuyerGroupId = ; inventTable.update(); } } ttsCommit; X++: while select ItemId from salesLine { select firstOnly forUpdate ItemType, ItemBuyerGroupId from inventTable where inventTable.ItemId == salesLine.ItemId; If (inventTable && (inventTable.ItemType == InventItemType::Item)) { ttsBegin; inventTable.ItemBuyerGroupId = ; inventTable.update(); ttsCommit; } }
__________________
Axapta book for developer |
|
![]() |
#3 |
MCT
|
Собственно написал, что бы было понятно ищущим знаний коллегам.
![]()
__________________
Axapta book for developer |
|
![]() |
#4 |
Участник
|
Я считаю что при необходимости вполне можно транзакцию вне цикла открывать... но вот потенциально бесконечный цикл....блин...как вижу этот true так в дрожь))))
|
|
|
За это сообщение автора поблагодарили: MikeR (2). |
![]() |
#5 |
Дмитрий Ерин
|
MikeR, в ваших примерах из п. 4 и 5 идет обработка плоских данных, для которых отмена части транзакций не критична, ибо они могут быть выполнены позже простым повторным запуском того же кода. А в исходном алгоритме (п. 1) идет обход узлов дерева, причем выполняется операция +=. Если такой обход раздробить на мелкие транзакции, то при их частичном откате восстановить целостность данных будет невозможно физически (если явно не хранить историю обновления).
Ну а пример из п. 2 (while select...) неприменим для обхода дерева при заданной в п.1 структуре данных. Наверное это вам и пытаются сказать... PS: С тем, что п.5 более корректен в общем случае, чем п.4 - согласен.
__________________
![]() |
|
![]() |
#6 |
MCT
|
Что сказали, то сказали, бумага все стерпит.
![]() С плоскими разобрались, так понимаю. НО ДАЖЕ в иерархической реализации это дает результат. Представляете если это достаточно большой пул проводок. Все напрочь блокируется, а какова вероятность, что произойдет исключительная ситуация? На практике это менее 5 процентов. Что стоит каждый раз терпеть блокировки или тупо следовать надуманной целостности, которая даже еще и не думала нарушаться... ![]() Не говоря о том, что по мелочам 1) X++: SELECT FIRSTONLY current WHERE current.InvGuid == InvGUID; InvGUID = current.ParentInvGUID; SELECT FIRSTONLY parent WHERE current.ParentInvGUID == parent.InvGUID; 2) X++: parentDistr.AMOUNTCUR += inventoryGuidInvoice.AmountCur;//слияние к предку ![]()
__________________
Axapta book for developer |
|
![]() |
#7 |
Британский учённый
|
Цитата:
![]()
__________________
Людям физического труда для восстановления своих сил нужен 7-8 часовой ночной сон. Людям умственного труда нужно спать часов 9-10. Ну а программистов будить нельзя вообще. |
|
|
За это сообщение автора поблагодарили: S.Kuskov (2). |
![]() |
#8 |
Участник
|
|
|
![]() |
#9 |
MCT
|
Скажем так, я переделал - работать стало ЗНАЧИТЕЛЬНО быстрее, сбоев не было вообще, проценты - это оценочное суждение
![]()
__________________
Axapta book for developer |
|
![]() |
#10 |
Banned
|
Цитата:
Сообщение от MikeR
![]() 5 Корректный код X++: while select ItemId from salesLine { select firstOnly forUpdate ItemType, ItemBuyerGroupId from inventTable where inventTable.ItemId == salesLine.ItemId; If (inventTable && (inventTable.ItemType == InventItemType::Item)) { ttsBegin; inventTable.ItemBuyerGroupId = ; inventTable.update(); ttsCommit; } } Что мешает при той же оптимизации выбирать внутри транзакции? Не знаю, у меня глаза режет от такого. Почему бы не так: X++: while select ItemId from salesLine { select firstOnly ItemType, ItemBuyerGroupId from inventTable where inventTable.ItemId == salesLine.ItemId; If (inventTable && (inventTable.ItemType == InventItemType::Item)) { ttsBegin; [B]inventTable.forupdate(true);[/B] inventTable.ItemBuyerGroupId = ; inventTable.update(); ttsCommit; } } ![]() |
|
![]() |
#11 |
MCT
|
Согласен, но это уже совсем мелкие детали.
Странно, что никто не заметил, что нет филд листа (тоже сорри за американизм/англицизм), слияния запросов, агрегирующей функции, но это тоже семечки, но на больших таблицах семечки уже серьезные. По while(true) и целостности вообще смотрю целая группировка даже существует. ![]()
__________________
Axapta book for developer Последний раз редактировалось MikeR; 22.01.2014 в 21:29. |
|
![]() |
#12 |
Участник
|
Цитата:
Сообщение от MikeR
![]() Для карсоты решения
![]() 5 Корректный код X++: while select ItemId from salesLine { select firstOnly forUpdate ItemType, ItemBuyerGroupId from inventTable where inventTable.ItemId == salesLine.ItemId; If (inventTable && (inventTable.ItemType == InventItemType::Item)) { ttsBegin; inventTable.ItemBuyerGroupId = ; inventTable.update(); ttsCommit; } } X++: while select ItemId from salesLine join inventTable where inventTable.itemid == salesLine.itemId && inventTable.ItemType == InventItemType::Item { update_recordset inventTableUpd setting inventTableUpd.ItemBuyerGroupId = where inventTableUpd.ItemId == salesLine.ItemId; } Объединение множественных обновлений в одну транзакцию - это конечно блокировки - но более производительный вариант для БД ИХМО. Последний раз редактировалось someOne; 23.01.2014 в 12:09. |
|
|
За это сообщение автора поблагодарили: mazzy (2), MikeR (3). |
![]() |
#13 |
MCT
|
someOne хороший варинат, если покурсовый не перекрыт.
__________________
Axapta book for developer |
|
![]() |
#14 |
Участник
|
|
|
![]() |
#15 |
Moderator
|
|
|
|
За это сообщение автора поблагодарили: S.Kuskov (1). |
Теги |
базовая информация, транзакции |
|
|