AXForum  
Вернуться   AXForum > Microsoft Dynamics AX > DAX: Программирование
All
Забыли пароль?
Зарегистрироваться Правила Справка Пользователи Сообщения за день Поиск

 
 
Опции темы Поиск в этой теме Опции просмотра
Старый 22.12.2010, 12:59   #1  
ice is offline
ice
Участник
Аватар для ice
Лучший по профессии 2014
 
1,738 / 404 (17) +++++++
Регистрация: 23.03.2006
! InventDim::findOrCreate
Решил поделиться интересной особенностью поведения InventDim::findOrCreate() в параллельных транзакциях. Для демонстрации запустите данный job на 2х клиентах. после запуска второго, продолжить первый (набор аналитик должен не существовать). В итоге сгенерится ошибка, что набор аналитик существует. Лечится ситуация с помощью UserConnection для findOrCreate()

X++:
static void job(Args _args)
{
    InventDim           inventDim;
    ;

    ttsbegin;
    inventDim.InventColorId = 'color1';
    inventDim.InventLocationId = 'Loc1';
    inventDim.InventSizeId = 'size1';
    inventDim = InventDim::findOrCreate(inventDim);
    Pause;
    ttscommit;
    info(inventdim.inventDimId);
}
Старый 22.12.2010, 13:23   #2  
S.Kuskov is offline
S.Kuskov
Участник
Лучший по профессии 2017
Лучший по профессии 2015
Лучший по профессии 2014
 
3,440 / 1775 (66) ++++++++
Регистрация: 28.04.2007
Адрес: Калуга
Цитата:
Сообщение от ice Посмотреть сообщение
Лечится ситуация с помощью UserConnection для findOrCreate()
Погодите лечить, давайте с диагнозом определимся.
Цитата:
Сообщение от ice Посмотреть сообщение
генерится ошибка, что набор аналитик существует
Может быть это не симптом, а защитная реакция организма?

На мой взгляд система всё сделала корректно. На первом кленте вы открываете транзакцию, в которой создаёте новую комбинацию кладских аналитик, но пока транзакция не закрыта запись в БД ещё не произошла (и это правильно). В это время второй клиент хочет воспользоваться такой же комбинацией, не видит её (её ещё нет в БД) и также пытается создать её. В результате как говориться кто первый - того и тапки. Нужно ли такое лечить? Не уверен.
Старый 22.12.2010, 14:01   #3  
ice is offline
ice
Участник
Аватар для ice
Лучший по профессии 2014
 
1,738 / 404 (17) +++++++
Регистрация: 23.03.2006
лечить нужно, т.к. не имеет смысла откатывать транзакцию по созданию новой комбинации, т.е. если такая комбинация раз произошла, то вполне возможно, что она еще раз произойдет, значит стоит ее создать и не откатывать, даже если вся транзакция прервалась с какой-либо ошибкой. а вторая транзакция уже воспользуется готовым набором аналитик и не будет ничего создавать

Последний раз редактировалось ice; 22.12.2010 в 14:04.
Старый 22.12.2010, 14:10   #4  
Владимир Максимов is offline
Владимир Максимов
Участник
КОРУС Консалтинг
 
1,701 / 1195 (43) ++++++++
Регистрация: 13.01.2004
Записей в блоге: 3
Присоединяюсь к S.Kustov. Это вовсе не ошибка, а вполне нормальная ситуация.

Кстати, стоит добавить, что UserConnection ничего не "вылечит", поскольку поиск выполняется в режиме "грязного чтения". Т.е. сценарий полностью повторится. Собственно, два разных клиента и так выполняются в разных Connection. Не понятно, как тут поможет тот факт, что добавится еще одно соединение.
Старый 22.12.2010, 14:23   #5  
ice is offline
ice
Участник
Аватар для ice
Лучший по профессии 2014
 
1,738 / 404 (17) +++++++
Регистрация: 23.03.2006
Цитата:
Сообщение от Владимир Максимов Посмотреть сообщение
Не понятно, как тут поможет тот факт, что добавится еще одно соединение.
userconnection создаст и завершит соединение(откроет и закроет транзакцию). т.о. набор аналитик останится существовать и ни какого грязного чтения
Старый 22.12.2010, 14:26   #6  
S.Kuskov is offline
S.Kuskov
Участник
Лучший по профессии 2017
Лучший по профессии 2015
Лучший по профессии 2014
 
3,440 / 1775 (66) ++++++++
Регистрация: 28.04.2007
Адрес: Калуга
Цитата:
Сообщение от Владимир Максимов Посмотреть сообщение
UserConnection ничего не "вылечит", поскольку поиск выполняется в режиме "грязного чтения".
Сдесь более важно то, что если действия по созданию новой комбинации будут вынесенны в отдельное соединение, то комбинация будет создана вне основной транзакции. Отрицательные последствия в том, что создание не отменится при откате транзакции.
Цитата:
Сообщение от ice Посмотреть сообщение
не имеет смысла откатывать транзакцию по созданию новой комбинации, т.е. если такая комбинация раз произошла, то вполне возможно, что она еще раз произойдет, значит стоит ее создать и не откатывать, даже если вся транзакция прервалась с какой-либо ошибкой.
Спорный вопрос.
Старый 22.12.2010, 14:31   #7  
ice is offline
ice
Участник
Аватар для ice
Лучший по профессии 2014
 
1,738 / 404 (17) +++++++
Регистрация: 23.03.2006
Цитата:
Сообщение от S.Kuskov Посмотреть сообщение
Сдесь более важно то, что если действия по созданию новой комбинации будут вынесенны в отдельное соединение, то комбинация будет создана вне основной транзакции. Отрицательные последствия в том, что создание не отменится при откате транзакции.

Спорный вопрос.
приведете отрицательные моменты того, что наборы аналитик останутся? (кроме увеличения количества строк)

Приведу пример положительный: происходят две разные долгие операции, вторая операция все это время ждет завершения первой т.к. не может выбрать или создать запись(inventDim). далее первая операция завершается. и тутже завершается вторая с ошибкой, хотя могло этого не произойти

Последний раз редактировалось ice; 22.12.2010 в 14:39.
Старый 22.12.2010, 14:57   #8  
S.Kuskov is offline
S.Kuskov
Участник
Лучший по профессии 2017
Лучший по профессии 2015
Лучший по профессии 2014
 
3,440 / 1775 (66) ++++++++
Регистрация: 28.04.2007
Адрес: Калуга
Цитата:
Сообщение от ice Посмотреть сообщение
приведете отрицательные моменты того, что наборы аналитик останутся? (кроме увеличения количества строк)
Не просто увеличение количества строк, а появление мусора в InventDim. Например в той же транзакции могут выделяется номера партий, серийные номера ещё какие-нибудь складские аналитики, создание которых будет отменено при откате транзакции, а в InventDim останутся несуществующие значения. На сколько это критично не возьмусь судить.
Старый 22.12.2010, 15:13   #9  
Владимир Максимов is offline
Владимир Максимов
Участник
КОРУС Консалтинг
 
1,701 / 1195 (43) ++++++++
Регистрация: 13.01.2004
Записей в блоге: 3
При чем здесь транзакция? Вы обратили внимание, что команда InventDim::find() выполняется БЕЗ второго параметра. Т.е. идет режим "грязного чтения" и факт наличия или отсутствия транзакции вообще никак не влияет. Да даже если и нет "грязного чтения". Все равно результат будет тот же самый.

Два пользователя "одновременно" начали создание одной и той же складской аналитики. Первый пользователь создал новую запись. А что должно произойти со вторым? Вполне логично, что его должно выбросить с сообщением об ошибке.

И какая разница, будет выполняться поиск в одной транзакции или в другой? Результат будет одинаковый - прерывание обработки. И ничем, никоим образом, здесь не поможет факт поиска в другой транзакции.

Теоретически, здесь могло бы помочь "зацикливание". Т.е. если произошла ошибка InventDim::FindOrCreate(), то делаем повторную попытку его выполнения. Но, здесь будут свои особенности.

Еще раз повторюсь. UserConnection - не поможет. Вам просто повезло. Стечение обстоятельств. Видимо, из-за дополнительной задержки, потребовавшейся на создание соединения поиск у второго "пользователя" произошел тогда, когда первый "пользователь" уже создал запись.
Старый 22.12.2010, 15:21   #10  
Владимир Максимов is offline
Владимир Максимов
Участник
КОРУС Консалтинг
 
1,701 / 1195 (43) ++++++++
Регистрация: 13.01.2004
Записей в блоге: 3
Для лучшего понимания процесса - по шагам:

- Первый пользователь выполнил InventDim::find() - ничего не нашел
- Второй пользователь выполнил InventDim::find() - ничего не нашел
- Первый пользователь создал запись inventDim
- Второй пользователь попытался создать запись InventDim - получил сообщение об ошибке

И чем здесь поможет выполнение операции поиска/создания в другом соединении? Да ничем!
Старый 22.12.2010, 15:43   #11  
ice is offline
ice
Участник
Аватар для ice
Лучший по профессии 2014
 
1,738 / 404 (17) +++++++
Регистрация: 23.03.2006
Цитата:
Сообщение от Владимир Максимов Посмотреть сообщение
Для лучшего понимания процесса - по шагам:

- Первый пользователь выполнил InventDim::find() - ничего не нашел
- Второй пользователь выполнил InventDim::find() - ничего не нашел
- Первый пользователь создал запись inventDim
- Второй пользователь попытался создать запись InventDim - получил сообщение об ошибке

И чем здесь поможет выполнение операции поиска/создания в другом соединении? Да ничем!
все у вас правильно, только момент между 1 и 3 очень маленький и вероятность вклинивания 2 очень мала. а вот вероятность попадания в описанную мной ситуацию очень большая
Старый 22.12.2010, 16:10   #12  
S.Kuskov is offline
S.Kuskov
Участник
Лучший по профессии 2017
Лучший по профессии 2015
Лучший по профессии 2014
 
3,440 / 1775 (66) ++++++++
Регистрация: 28.04.2007
Адрес: Калуга
Цитата:
Сообщение от Владимир Максимов Посмотреть сообщение
Для лучшего понимания процесса - по шагам: ...
На сколько я себе это представляю, модель процесса немного другая:
1. Первый пользователь открыл транзакцию
2. Первый пользователь выполнил InventDim::find() - ничего не нашел
3. Первый пользователь "создал" запись inventDim
4. Второй пользователь открыл транзакцию
5. Второй пользователь выполнил InventDim::find() - ничего не нашел (т.к. первый ещё не закрыл транзакцию)
6. Второй пользователь "создал" запись inventDim
7. Первый пользователь закрыл транзакцию (только тут запись пошла в БД)
8. Второй пользователь попытался закрыть транзакцию - получил сообщение об ошибке

По идее, если на шаге 7 первым транзакцию закроет второй пользователь, то ошибку получит первый.
Старый 22.12.2010, 16:31   #13  
ice is offline
ice
Участник
Аватар для ice
Лучший по профессии 2014
 
1,738 / 404 (17) +++++++
Регистрация: 23.03.2006
Цитата:
Сообщение от S.Kuskov Посмотреть сообщение
На сколько я себе это представляю, модель процесса немного другая:
1. Первый пользователь открыл транзакцию
2. Первый пользователь выполнил InventDim::find() - ничего не нашел
3. Первый пользователь "создал" запись inventDim
4. Второй пользователь открыл транзакцию
5. Второй пользователь выполнил InventDim::find() - ничего не нашел (т.к. первый ещё не закрыл транзакцию)
6. Второй пользователь "создал" запись inventDim
7. Первый пользователь закрыл транзакцию (только тут запись пошла в БД)
8. Второй пользователь попытался закрыть транзакцию - получил сообщение об ошибке

По идее, если на шаге 7 первым транзакцию закроет второй пользователь, то ошибку получит первый.
6п не произойдет, т.к будет ожидать завершение транзакции первого пользователя
За это сообщение автора поблагодарили: S.Kuskov (1).
Старый 22.12.2010, 20:20   #14  
Владимир Максимов is offline
Владимир Максимов
Участник
КОРУС Консалтинг
 
1,701 / 1195 (43) ++++++++
Регистрация: 13.01.2004
Записей в блоге: 3
Цитата:
Сообщение от ice
все у вас правильно, только момент между 1 и 3 очень маленький и вероятность вклинивания 2 очень мала. а вот вероятность попадания в описанную мной ситуацию очень большая
Ничего подобного. Я просто описал тот процесс, который Вы и пытаетесь симулировать. Т.е. попытку "одновременного" создания записи двумя пользователями. Поскольку для процессора такого понятия в принципе не существует, то, с точки зрения процессора, эта самая "одновременность" будет разбита именно на описанные мною шаги.

Если подходить с точки зрения стороннего наблюдателя, то будет казаться, что выполняются следующие процессы

1. Оба пользователя "одновременно" открыли транзакцию
2. Оба пользователя "одновременно" выполнили поиск аналитики.
3. Оба пользователя "одновременно" ничего не нашли
4. Оба пользователя "одновременно" попытались создать новую запись. Один создал, другой "завис" до завершении транзакции первого пользователя
5. Первый пользователь завершил транзакцию, второй попытался создать запись - получил ошибку

Но поскольку "одновременность" - это иллюзия, создаваемая компьютером, то логично разбить процесс на понятные последовательные этапы. Что я и сделал в самом начале.

Однако во всей этой схеме "тонкий" момент - это момент поиска. Поиск осуществляется командой

select inventDim where ...

И вот тут-то и возникает вопрос настроек "по умолчанию". Причем настроек именно AOS.

Если настройки по умолчанию предполагают, что подобный запрос уйдет на сервер с хинтами грязного чтения, то 100% получим ошибку. И дополнительное соединение здесь никак не поможет. Поскольку в этом дополнительном соединении запрос также пойдет с хинатми грязного чтения

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

В этом случае сценарий будет похож на то, что описал S.Kuskov, но с одной существенной поправкой:

1. Оба пользователя "одновременно" открыли транзакцию
2. Оба пользователя "одновременно" начали поиск
3. Один из них закончил поиск первым и успел создать запись
4. Тогда другой "подвиснет" в процессе поиска и его поиск останется не завершенным до окончания транзакции первого пользователя
5. Первый пользователь завершил транзакцию
6. Второй пользователь продолжил поиск и нашел запись созданную первым
7. Второй пользователь также успешно завершил транзакцию

Конфликта вообще не будет. И это-то как раз наиболее вероятный сценарий. Поскольку полная "одновременность" завершения поиска двумя пользователями - это, скорее, исключительная ситуация. И дополнительное соединение здесь опять роли не играет, поскольку также будет ждать завершения транзакции первого пользователя.

А отсюда возвращаемся к вопросу

Цитата:
Сообщение от _scorp_
Может у Вас включены какие-то дополнительные хинты для SQL?

PS: Кстати, "случайно" режим кеширования таблицы InventDim не меняли?
Старый 22.12.2010, 21:36   #15  
S.Kuskov is offline
S.Kuskov
Участник
Лучший по профессии 2017
Лучший по профессии 2015
Лучший по профессии 2014
 
3,440 / 1775 (66) ++++++++
Регистрация: 28.04.2007
Адрес: Калуга
Цитата:
Сообщение от Владимир Максимов Посмотреть сообщение
дополнительное соединение здесь никак не поможет. Поскольку в этом дополнительном соединении запрос также пойдет с хинатми грязного чтения
Дополнительное соединение призвано изменить поведение не второго клиента (для него действительно принципиально ничего не измениться), а первого! Суть в том что если первый клиент не будет откладывать вставку нового значения в InventDim до завершения своей транзакции (используя дополнительное соединение это возможно, верно?), то к моменту когда второй клиент будет искать заданную комбинацию - он её найдёт(!). При этом основная транзакция первого клиента может быть ещё не завершена. Ещё раз, дополнительное соединение используется для выноса действий по вставке значения из основной транзакции (длинной) в отдельную (короткую).

Цель - получить следующую последовательность действий:
1. Первый пользователь открыл основную транзакцию
2. ...Первый пользователь открыл фоновую транзакцию в отдельном соединении
3. ...Первый пользователь в отдельном соединении выполнил findOrCreate
4. ...Первый пользователь подтвердил фоновую транзакцию (новая комбинация складских аналитик окончательно запостилась в таблицу)
5. Второй пользователь открыл свою транзакцию
6. Второй пользователь выполнил InventDim::find() - нашёл запись!
7. Второй пользователь подтвердил свою транзакцию
8. Первый пользователь подтвердил свою основную транзакцию

Последний раз редактировалось S.Kuskov; 22.12.2010 в 22:05.
Старый 22.12.2010, 22:03   #16  
ice is offline
ice
Участник
Аватар для ice
Лучший по профессии 2014
 
1,738 / 404 (17) +++++++
Регистрация: 23.03.2006
Цитата:
Сообщение от S.Kuskov Посмотреть сообщение
Дополнительное соединение призвано изменить поведение не второго клиента (для него действительно принципиально ничего не измениться), а первого! Суть в том что если первый клиент не будет откладывать вставку нового значения в InventDim до завершения своей транзакции (используя дополнительное соединение это возможно, верно?), то к моменту когда второй клиент будет искать заданную комбинацию - он её найдёт(!). При этом основная транзакция первого клиента может быть ещё не завершена. Ещё раз, дополнительное соединение используется для выноса действий по вставке значения из основной транзакции (длинной) в отдельную (короткую).
да именно так. первая транзакция может длиться, например, несколько часов, а если расматривать время отдельной транзакции по вставке inventdim, то это произойдет гораздо быстрее, и к моменту чтения вторым клиентом, запись будет существовать
Старый 22.12.2010, 16:46   #17  
_scorp_ is offline
_scorp_
Участник
Аватар для _scorp_
MCBMSS
 
488 / 369 (13) ++++++
Регистрация: 25.07.2007
Адрес: Москва
Цитата:
Сообщение от ice Посмотреть сообщение
... В итоге сгенерится ошибка, что набор аналитик существует.
AX 3.0. Транзакция второго пользователя ждет окончания выполнения транзакции первого. После завершения первой транзакции, вторая нормально отрабатывает без всяких ошибок.
AX 4.0 Транзакция второго пользователя не ждет завершения первой транзакции. Отрабатывает в любой последовательности и без ошибок.
AX 2009 нет под рукой, проверить не могу. Но там, кстати, появился
X++:
Exception::DuplicateKeyException
, который может отлавливать такие ситуации.

Может у Вас включены какие-то дополнительные хинты для SQL? У меня ошибка не появляется.
Старый 22.12.2010, 17:11   #18  
ice is offline
ice
Участник
Аватар для ice
Лучший по профессии 2014
 
1,738 / 404 (17) +++++++
Регистрация: 23.03.2006
Цитата:
Сообщение от _scorp_ Посмотреть сообщение
AX 3.0. Транзакция второго пользователя ждет окончания выполнения транзакции первого. После завершения первой транзакции, вторая нормально отрабатывает без всяких ошибок.
AX 4.0 Транзакция второго пользователя не ждет завершения первой транзакции. Отрабатывает в любой последовательности и без ошибок.
AX 2009 нет под рукой, проверить не могу. Но там, кстати, появился
X++:
Exception::DuplicateKeyException
, который может отлавливать такие ситуации.

Может у Вас включены какие-то дополнительные хинты для SQL? У меня ошибка не появляется.
а какой результат в каждом случае?
PS у меня ax2009 sql2008
Старый 22.12.2010, 17:19   #19  
_scorp_ is offline
_scorp_
Участник
Аватар для _scorp_
MCBMSS
 
488 / 369 (13) ++++++
Регистрация: 25.07.2007
Адрес: Москва
Цитата:
Сообщение от ice Посмотреть сообщение
а какой результат в каждом случае?
info выдает одинаковый номер аналитики и в 3.0 и в 4.0.
Старый 22.12.2010, 17:37   #20  
Evgeniy2020 is offline
Evgeniy2020
Участник
 
309 / 68 (3) ++++
Регистрация: 10.04.2007
Адрес: Москва, САО, СЗАО
Доделать также, как с генерированием numbersequence.
с выделением нового номера.
 

Похожие темы
Тема Автор Раздел Ответов Посл. сообщение
Вопросы по ReleaseUpdate DAX 2009 ansoft DAX: Программирование 7 31.08.2010 12:21
lookup для ItemId iz InventTable + InventDim + InventSum stalker25 DAX: Программирование 6 20.07.2009 15:50
inventUpd_reservation использование inventDim SHiSHok DAX: Программирование 2 31.03.2007 21:32
InventDim.findOrCreateBlank - простое сложно? Pavlo AKA Panok DAX: Программирование 5 25.10.2004 16:50
Работа с InventDim... NJD DAX: Программирование 11 17.06.2004 14:42

Ваши права в разделе
Вы не можете создавать новые темы
Вы не можете отвечать в темах
Вы не можете прикреплять вложения
Вы не можете редактировать свои сообщения

BB коды Вкл.
Смайлы Вкл.
[IMG] код Вкл.
HTML код Выкл.
Быстрый переход

Рейтинг@Mail.ru
Часовой пояс GMT +3, время: 10:56.