13.12.2019, 13:36 | #1 |
Участник
|
AX 2012 R3. Включить OCC на InventSum и выжить
И снова хочу поделиться success-story.
Готовились к черной пятнице и проводили нагрузочные тестирования. Заметили блокировки при большом числе web-вызовов по операциям резервирования по заказам на продажу на InventSum. Нагрузка была такая, что даже номерную серию SalesId пришлось на последовательности в базе MSSQL перевести. Пришла в голову идея таки включить OCC (оптимистические блокировки) на InventSum. Если посмотреть код на InventUpdateOnhand.ttsNotifyPreCommit, то можно заметить, что COMMIT выполняется логично, но крайне избыточно.
Схема красивая рабочая с минимальными блокировками в конце комита, но ... Хочется включить оптимистические блокировки. Если в лоб на таблице InventSum включить OCC, то получаем проблему, когда групповой запрос не обновляет RecVersion, а единичный обновляет измененные строки из-за того, что вычитал старые данные, обновил в памяти кол-во и не упал на обновлении из-за совпадающего RecVersion. Ну и дополнительные выборки с пессимистиком, только чтобы залочить строки перед групповым обновлением. Чего удалось достичь:
В итоге блокировки InventSum ушли и подсистема резервирования (по сути любые операции обновления InventSum) стала выдерживать гораздо большие нагрузки от веб-сервисов. Если случаются коллизии при резервировании, когда 2 клиента пытаются одновременно зарезервировать последнюю единицу товара, то транзакция откатится на этапе проверки отрицательных остатков (как было и раньше). Огромная торговая компания розница + интернет магазин в черную пятницу отлично себя чувствовали при онлайн резервировании. |
|
|
За это сообщение автора поблагодарили: AlGol (2), Logger (10), gl00mie (15), SRF (7), imir (2). |
16.12.2019, 05:01 | #2 |
Участник
|
Цитата:
Сообщение от kgksoft
Заметили блокировки при большом числе web-вызовов по операциям резервирования по заказам на продажу на InventSum. Нагрузка была такая, что даже номерную серию SalesId пришлось на последовательности в базе MSSQL перевести. Пришла в голову идея таки включить OCC (оптимистические блокировки) на InventSum.
1. О каком кол-ве операций(в час к примеру) идет речь 2. Почему не использовали предварительное выделение номеров 3. Как я понял вы сделали обновление на SQL вне зависимости от кол-ва строк. OCC это же сво-во в АХ, как оно влияет вообще на ? 4. Какой объем InventSum если выполнить следующий скрипт X++: select count(*) as number, Closed,ClosedQty from InventSum (nolock) Group by Closed, ClosedQty |
|
16.12.2019, 11:00 | #3 |
Участник
|
Цитата:
Сообщение от trud
Поздравляю с решением проблемы, но описание не очень понятно.
1. О каком кол-ве операций(в час к примеру) идет речь 2. Почему не использовали предварительное выделение номеров 3. Как я понял вы сделали обновление на SQL вне зависимости от кол-ва строк. OCC это же сво-во в АХ, как оно влияет вообще на ? 4. Какой объем InventSum если выполнить следующий скрипт
|
|
17.12.2019, 07:14 | #4 |
Участник
|
Цитата:
Сообщение от kgksoft
Во время тестирования наблюдались блокировки на вызовах select updlock, которые пытались залочить строки для обновления. После переделки блокировки ушли.
Происходило две операции (Блокировка и Обновление), а теперь блокировка происходит на уровне SQL одной операцией update qty += delta. Т.е. в ttsNotifyPreCommit происходит блокировка (с pessimistic lock) InventSum в разрезе ItemId-InventDimId, далее по этому же ключу происходит обновление(при этом используются 2 ветки - прямой SQL и одна запись). Т.е. от того что вы просто поменяете все на прямой SQL думаю ничего принципиально не изменится, все равно будут накладываться блокировки в разрезе ItemId-InventDimId(что правильно). |
|
17.12.2019, 10:56 | #5 |
Участник
|
Цитата:
Сообщение от trud
А о каких операциях идет речь? Разве в стандарте кто-то лочит InventSum, кроме этого финального триггера? или это какой-то кастомный функционал?
Т.е. в ttsNotifyPreCommit происходит блокировка (с pessimistic lock) InventSum в разрезе ItemId-InventDimId, далее по этому же ключу происходит обновление(при этом используются 2 ветки - прямой SQL и одна запись). Т.е. от того что вы просто поменяете все на прямой SQL думаю ничего принципиально не изменится, все равно будут накладываться блокировки в разрезе ItemId-InventDimId(что правильно). В моем случае было много параллельных операций по резервированию и разрезервированию товара. Товар и аналитики могли пересекаться. Именно при большой нагрузке с интернета и розницы происходили небольшие блокировки на InventSum. В стандарте все верно написано, но с моими исправлениями эта подсистема позволяет держать большие нагрузки по параллельной работе с одинаковыми аналитиками. Обновление InventSum перестало быть самым узким местом при резервирование большого потока заказов. Тестировали протоком реальных заказов JMeter, потом шла операция разрезервирования этих заказов. Скорость была около 300 вызовов в минуту. Повторюсь внутри не только резервирование, а и построение цепочек заказов (закупки + перемещения + заказы на продажу). |
|
17.12.2019, 12:24 | #6 |
Участник
|
Цитата:
Сообщение от kgksoft
Все верно. Ничего нестандартного в процессе резервирования не использовали. Но вставка, блокировка + обновление медленнее, чем одна операция по обновлению. Это высоконагруженные веб-сервисы и тут каждая лишняя операция в базу данных дорога. А у меня в базе доходит до 90000 операций в секунду.
Цитата:
Если у вас до 5 позиций, то это проверка должна выполняться мнгновенно и никаких блокировкок быть не должно, ну т.е. вы сами посчитайте, 5 заказов в секунду, наихудший случай, когда в каждом одна и таже аналитика и номенклатура, завершение к примеру идет 100мс (что довольно долго) и то не получается блокировок НО В начальных версиях 2012 R3 существовал баг, когда из-за неправильных индексов по InventSumDelta, InventSumDeltaDim эта проверка остатков выбирала неправильный план и выполнялась довольно долго. тогда да, на любой серьезной нагрузке система вставала Проблема собственно описана https://axology.wordpress.com/2013/1...umdelta-table/ решением было удаление индексов(всех кроме 1) на указанных таблицах |
|
|
За это сообщение автора поблагодарили: Logger (5), axotnik88 (1). |
17.12.2019, 17:59 | #7 |
Участник
|
Цитата:
Цитата:
Сообщение от trud
Но ведь параллельные операции InventSum не блокируют, она блокируется в самом конце, т.е. важно сколько параллельных завершений транзакций было и сколько выполнялась проверка остатков в этом завершение транзакции. Вы это замеряли?
Если у вас до 5 позиций, то это проверка должна выполняться мнгновенно и никаких блокировкок быть не должно, ну т.е. вы сами посчитайте, 5 заказов в секунду, наихудший случай, когда в каждом одна и таже аналитика и номенклатура, завершение к примеру идет 100мс (что довольно долго) и то не получается блокировок НО В начальных версиях 2012 R3 существовал баг, когда из-за неправильных индексов по InventSumDelta, InventSumDeltaDim эта проверка остатков выбирала неправильный план и выполнялась довольно долго. тогда да, на любой серьезной нагрузке система вставала Проблема собственно описана https://axology.wordpress.com/2013/1...umdelta-table/ решением было удаление индексов(всех кроме 1) на указанных таблицах Удалять индексы не стану, но автообновление статистики наверное отключу. Спасибо за статью. |
|
17.12.2019, 18:48 | #8 |
Участник
|
Вообще это странно. Неужели у вас такое количество одновременных резервирований по одинаковому сочетанию номенклатуры и аналитики?
Мне кажется дело в другом. Срабатывает страничная эскалация блокировок. У нас было такое на старте. Нужно отключить page lock на всех индексах inventsumdelta. Ну и план гайдов добавить, чтобы оптимизатор не сбивался с планами запросов. По мне включение occ на остатках это очень опасный ход. Ведь в этом суть блокировок - не дать продать в минус, если в этот момент кто-то уже продает то же самое. |
|
18.12.2019, 03:19 | #9 |
Участник
|
Цитата:
Т.е. решение тут - с InventSumDelta и InventSumDeltaDim удаляете все индексы(включая индекс по RecId), оставляете один кластерный - это уберет проблему выбора индекса, так как он будет 1 Это должно помочь. Ну или можете заморочиться с план гайдами как написал sonik Последний раз редактировалось trud; 18.12.2019 в 03:22. |
|
18.12.2019, 09:54 | #10 |
Участник
|
А кроме Романа Долгополова (db / RDOL) никто не пытался бороться с блокировками на InventSumDelta, преобразованием ее в TempDB ? В АХ 2012 это проще, чем в АХ 2009.
Цитата:
Сообщение от db
... В моем случае темповыми стали InventSumDelta и LedgerBalancesTransDelta. Результат - ПОЛНОЕ отсутствие блокировок при обновлении запасов в наличии и балансов по ГК. Полное означает не облегчение, а устранение проблемы на корню и возможность многопоточной разноски документов в тысячи реально параллельных не ждущих друг друга потоков. И такие странные методы стоили достигнутого результата
|
|
18.12.2019, 10:58 | #11 |
Участник
|
Цитата:
Сообщение от sonik
Вообще это странно. Неужели у вас такое количество одновременных резервирований по одинаковому сочетанию номенклатуры и аналитики?
Мне кажется дело в другом. Срабатывает страничная эскалация блокировок. У нас было такое на старте. Нужно отключить page lock на всех индексах inventsumdelta. Ну и план гайдов добавить, чтобы оптимизатор не сбивался с планами запросов. По мне включение occ на остатках это очень опасный ход. Ведь в этом суть блокировок - не дать продать в минус, если в этот момент кто-то уже продает то же самое. Цитата:
Сообщение от trud
Скорее всего в этом проблема. Работа с данной таблицей всегда должна происходить в рамках сессии т.е. если вам понадобился индекс где нет TTSID, то ваши планы начинают свое выполнение не с этой таблицы(это и приводит к тормозам). Т.е. если у вас 5 строк, то при выполнение join сложность выборки всегда должна равняться 5 строкам. Но если SQL выбирает неправильный план и у вас начинается выборка с InventDim(ключевое слово тут paremeters sniffing), то тут скорее всего и начинаются тормоза, ибо судя по размеру InventSum данных у вас много и сканирование может уйти в тысячи записей
Т.е. решение тут - с InventSumDelta и InventSumDeltaDim удаляете все индексы(включая индекс по RecId), оставляете один кластерный - это уберет проблему выбора индекса, так как он будет 1 Это должно помочь. Ну или можете заморочиться с план гайдами как написал sonik Цитата:
Сообщение от Alexius
А кроме Романа Долгополова (db / RDOL) никто не пытался бороться с блокировками на InventSumDelta, преобразованием ее в TempDB ? В АХ 2012 это проще, чем в АХ 2009.Временные SQL таблички в ax2009
|
|
18.12.2019, 14:25 | #12 |
Участник
|
Цитата:
Сообщение от kgksoft
Суть в том, что из-за врожденной оптимистичности при выборе остатка при резервировании система подбирает всегда один и тот же остаток товара с одним и тем же серийным номером (сортировки остатка по фифо, партиям, датам прихода). Т.е. одновременно в InventSumDelta двумя параллельными процессами пытается списывать один и тот же товар с одним серийником.
|
|
20.12.2019, 02:19 | #13 |
Участник
|
|
|
20.12.2019, 09:59 | #14 |
Участник
|
На сколько я понял, проблема в автоподборе складской аналитики "Серийный номер". Если в процессе автоподбора накладывать блокировки на таблицу серийных номеров с хинтом ReadPast, то проблема попадания одного и того же серийника в разные документы уйдет.
|
|
20.12.2019, 12:47 | #15 |
Участник
|
Да, думаю такой вариант подойдет. Если не удалось заблокировать, то перейти к следующему кандидату. Тогда можно и про временный InventSumDelta подумать. Спасибо
|
|
Теги |
inventsum, inventsumdelta, occ |
|
|