>> Что именно улучшить? Скорость работы? Надежность? Время написания?
Добавлю еще к предыдущим.
Возможно, будет быстрее работать. Но тут может по-разному быть. Транзакций будет больше, поэтому может быть медленнее из-за более частых коммитов. Это фактор замедления.
Но!
Если строк в заявке будет много, то в случае одной транзакции (как у вас) растет время ожидания так как пока 1-я сессия не завершит резервирование всей заявки с Х строками, другая сессия которая, возможно, ее ждет, не начнет работу, ждет пока блокировки снимутся. В случае коротких транзакций они меньше будут друг другу мешать, меньше ожидание. Быстрее работа.
Какой из факторов сильнее скажется заранее сложно спрогнозировать. Если строк много и большая конкуренция за остатки то вариант с 1 транзакцией на строку будет быстрее. А если нет, то может быть обратный эффект.
>> Что именно улучшить? Скорость работы? Надежность? Время написания?
Снизить вероятность блокировок - я об этом явно написал.
Масштабируемость будет лучше. Если вдруг изменятся условия и в заявке для резервирования число строк увеличится например в 100 - 1000 раз, то работать будет норм. И примерно с той же скоростью на 1 строку (меньше будет ожидание разными сессиями друг друга). Конечно код будет сложнее, как вы справедливо указали. Но ничего бесплатно не бывает.
>> Можете пример кода привести, который демонстрирует эти улучшения?
Собственно, я описал идею и пошагово все привел. что там непонятного ? Или это придирка такая ? Ну кто хочет понять тот ищет возможности, кто не хочет - ищет причины.
>> Я пока увидел, что для реализации цикла с транзакциями внутри, а не снаружи нужен фоновый процесс, который будет отменять незавершенные брони. Тогда как в моем примере из статьи такой процесс не нужен.
Он потребуется для обработки аварийных ситуаций как минимум. Но и в вашем примере он нужен, о чем я указал.
Могу подробнее пояснить.
Вот приходит в вашем примере заявка - делается резерв, коммитится транзакция, а тут все падает (например электричество вырубилось или виртуальная машина грохнулась). Транзакция закоммичена. А оплата не прошла. Как в вашем примере решалась бы эта проблема ? Все равно нужно стороннее вмешательство для снятия резерва или восстановления сессии в которой можно было бы провести оплату.
>> Если для вас ACID и гарантии СУБД это "догмы" и "ярлыки", тогда вы правы.
Вы просто подменяете понятия, приписываете мне то что я не говорил, а потом "опровергаете". Гаденький, но детский приемчик. И совсем вас не украшает. На него никто уже не ведется.
Касательно транзакций и ACID - а кто вам сказал что вся обработка должна идти в одной транзакции ? Это совсем не обязательно. Все определяется задачей. Тем на какие по смыслу шаги можно разделить обработку (а в некоторых случаях и распараллелить, но это уже другая тема). В зависимости от условий, допустимо последовательность действий разбивать на несколько последовательных транзакций. И это не нарушение ACID. Нужно просто понимать что делаешь и соотносить с практикой.
"гораздо менее надёжный, чем использование транзакций."?
Вы серьезно?
Да вы видимо никогда не сталкивались с кучей блокировок из за больших транзакций. Вам что важно, надежность или мнимая "простота"? И зачем она будет если повиснет под нагрузкой.
Насчет резервов - можно предположить экзотический сценарий когда из за падения обработки останется зависший резерв по части строк. Так он по куче причин может быть. Например в вашем случае, резерв полностью прошел но оплата не прошла. Или электрисество вырубилось. Та же ситуация только больше зарезервированных строк.
Для разруливания таких ситуаций делают фоновые обработки, которые снимаю старые ненужные рещервы или такие вот аварийные заказы. Обычная ситуация. И вы без такой обработки не обойдетесь даже с вашим вариантом длинных транзакций.
Почему вы решили что это достигается заключением обработки всех строк в одну транзакцию?
Все завсит от поставленной задачи.
Можно условиться так.
В шапке документа ставится пометка что начат резерв (например статус Начато резервирование)
Затем идет резервирование строк, в каждой транзакции обрабатывается Х строк.
В конце переводим статус в шапке "Зарезервировано"
если операция прервана, сервер бд упал, электричество вырубилось итп. В следующий раз мы увидим документ находящийся с большой вероятностью в промежуточном статусе "Начато резервирование". В такой ситуации можно продолжить процесс с того же места. Или если потребуется, запустить откат статуса - снятие резерва.
Зависит от обстоятельств все.
Я недавно, как раз подобную задачу решал.
Идет продажа. При пробитии чека обновляется аналитика "дата пролажи" для товара. И тут выяснилось что все виснет.
Оказывается спецы по олап системе решили раз в месяц закачивать измененные аналитики. Делали это через специальный документ - шапка и строки. В строках аналитика и товар. При утверждении документа, аналитики проливабтся из строк в свойства товаров.
Ну и олапщики закачали 110 тыщ строк в документ и запустили утверждение. На кассе все повисло.
Что тут быстро сделать?
Порезал процесс утверждения на множество транзакций по 50 строк на транзакцию. Все проблемы ушли.
Если утверждение прервалось, можно продолжить с того же места.
Условия могуть быть разными и их определяет бизнес. Я 12 лет проработал в компании дистрибьюторе. Там сеть магазинов, например 7й континет делала регулярно кучу заказов по заказу на магазин. В каждом заказе десятки товаров, обычно от 40 до 100. Заказ можно было отгружать если процент зарезервированных строк был не меньше какого то числа. То ли 60% то ли 70. За давностью лет уже не помню. К тому же заказ делался за несколько дней до отгрузки так что в течение дня попытка резервирования могла повторяться несколько раз (чтобы повысить % резервирования в случае если где то отказались от резерва или новый товар поступил).
Если требования бизнеса такие как вы предполагаете, то нет никакой проблемы снять резерв (можно в блоке catch принять это решение).
Движок бд откатит транзакцию так же как и в случае одной транзакции на кучу строк.
Или вас беспокоит в каком статусе получится документ в целом, если в нем по части строк резерв прошел успешно а в части нет?
Так есть же try catch. Ситуация ловится и обрабатывается снова.
Кстати, встречал на практике документы и на 2 - 3 тысячи строк. Когда из магазинов заливали сгруппированные по магазинам данные реализации за весь день.
Встречался на практике с такой проблемой. Обычно помогает разбиение не более короткие транзакции. Ну например если типичный документ содержит 50 строк, то зачем делать резерв в одной транзакции? Можно по транзакции на строку.
Наивно ожидать, что другие мессенджеры так не будут делать, или что их владельцев не прогнут сильные мира сего (Дурова просто так что ли прессовали во франции)
И проверить вы не можете. Косвенно предполагать - да. Но надежнее исходить из самых худших и реалистичных предположений - что все сливается.
Возможно станут популярнее SOC когда cpu и память в одном чипе как в apple M1,2,3,4....
Интересно когда amd до такого дозреют.
Нервно курит в сторонке ваш ркн :)
Перенимает опыт.
Прекрасно !
Будут ли его читать ...
>> Что именно улучшить? Скорость работы? Надежность? Время написания?
Добавлю еще к предыдущим.
Возможно, будет быстрее работать. Но тут может по-разному быть. Транзакций будет больше, поэтому может быть медленнее из-за более частых коммитов. Это фактор замедления.
Но!
Если строк в заявке будет много, то в случае одной транзакции (как у вас) растет время ожидания так как пока 1-я сессия не завершит резервирование всей заявки с Х строками, другая сессия которая, возможно, ее ждет, не начнет работу, ждет пока блокировки снимутся. В случае коротких транзакций они меньше будут друг другу мешать, меньше ожидание. Быстрее работа.
Какой из факторов сильнее скажется заранее сложно спрогнозировать. Если строк много и большая конкуренция за остатки то вариант с 1 транзакцией на строку будет быстрее. А если нет, то может быть обратный эффект.
>> Что именно улучшить? Скорость работы? Надежность? Время написания?
Снизить вероятность блокировок - я об этом явно написал.
Масштабируемость будет лучше. Если вдруг изменятся условия и в заявке для резервирования число строк увеличится например в 100 - 1000 раз, то работать будет норм. И примерно с той же скоростью на 1 строку (меньше будет ожидание разными сессиями друг друга). Конечно код будет сложнее, как вы справедливо указали. Но ничего бесплатно не бывает.
>> Можете пример кода привести, который демонстрирует эти улучшения?
Собственно, я описал идею и пошагово все привел. что там непонятного ? Или это придирка такая ? Ну кто хочет понять тот ищет возможности, кто не хочет - ищет причины.
>> Я пока увидел, что для реализации цикла с транзакциями внутри, а не снаружи нужен фоновый процесс, который будет отменять незавершенные брони. Тогда как в моем примере из статьи такой процесс не нужен.
Он потребуется для обработки аварийных ситуаций как минимум. Но и в вашем примере он нужен, о чем я указал.
Могу подробнее пояснить.
Вот приходит в вашем примере заявка - делается резерв, коммитится транзакция, а тут все падает (например электричество вырубилось или виртуальная машина грохнулась). Транзакция закоммичена. А оплата не прошла. Как в вашем примере решалась бы эта проблема ? Все равно нужно стороннее вмешательство для снятия резерва или восстановления сессии в которой можно было бы провести оплату.
>> Если для вас ACID и гарантии СУБД это "догмы" и "ярлыки", тогда вы правы.
Вы просто подменяете понятия, приписываете мне то что я не говорил, а потом "опровергаете". Гаденький, но детский приемчик. И совсем вас не украшает. На него никто уже не ведется.
Касательно транзакций и ACID - а кто вам сказал что вся обработка должна идти в одной транзакции ? Это совсем не обязательно. Все определяется задачей. Тем на какие по смыслу шаги можно разделить обработку (а в некоторых случаях и распараллелить, но это уже другая тема). В зависимости от условий, допустимо последовательность действий разбивать на несколько последовательных транзакций. И это не нарушение ACID. Нужно просто понимать что делаешь и соотносить с практикой.
Я вам пишу как можно улучшить и сделать надежнее несильно усложняя код.
Я этим больше 20 лет занимаюсь. Практикой все проверено.
А вы какими догмами рассуждаете.
Ярлыки навешиваете.
Ну, делайте как вам нравится. Никто не заставляет.
"гораздо менее надёжный, чем использование транзакций."?
Вы серьезно?
Да вы видимо никогда не сталкивались с кучей блокировок из за больших транзакций. Вам что важно, надежность или мнимая "простота"? И зачем она будет если повиснет под нагрузкой.
Насчет резервов - можно предположить экзотический сценарий когда из за падения обработки останется зависший резерв по части строк. Так он по куче причин может быть. Например в вашем случае, резерв полностью прошел но оплата не прошла. Или электрисество вырубилось. Та же ситуация только больше зарезервированных строк.
Для разруливания таких ситуаций делают фоновые обработки, которые снимаю старые ненужные рещервы или такие вот аварийные заказы. Обычная ситуация. И вы без такой обработки не обойдетесь даже с вашим вариантом длинных транзакций.
А можете озвучить цифры, сколько запросов на резерв в секунду у вас было в среднем и в пике?
Да причем здесь WAL?
Это же другой уровень. Все в приложении делается. Промежуточный статус млжно клиенту не показывать.
Ну вот рассмотрим ваш пример.
Клиент делает запрос - зарезервировать Х билетов.
В вашем примере
код открывает транзакцию.
Начинает цикл по числу билетов.
На каждом шаге цикла выполняет резервирование.
В конце после цикла закрывает транзакцию.
Возвращает ответ клиенту об успехе (дальше пойдет оплатп)
А как я предлагаю
Начинает цикл по числу билетов
На каждом шаге цикла делаем
А. Открываем транзакцию
Б. Делаем резерв одного билета.
В. Закрываем транзакцию
После завершения цикла возвращаем ответ об успехе (дальше идет оплата)
По факту, 2 строки кода поменять и все.
Можно чуть усложнить, в каждой транзакции несколько билетов резервировать на гаге Б. - тогда будет меньше накладных расходов.
Да, он просто задирал требования и дрючил студентов почем зря. Это не говорит о том что хорошо преподавал предмет.
Трепет первокуров...
Ну о чем вы. Даже несерьезно обсуждать.
>> Беклемишев — вершина, изумруд даже, можно сказать, Физтеха
С каких то пор он вершина и изумруд? Вы чего то попутали. Никогда такого отношения к нему не было.
Если что - закончил ФУПМ 2002. Так что с предметом знаком.
Вариант с хранимкой БЕЗ SELECT FOR UPDATE + с проверкой остатка в конце, в логах консольки пусто, цифры в конце сходятся, скорость 300 rps
Примерно такое решение реализовано в erp dynamics axapta от microsoft. Работает с 4-й версии (выпущена в 2008-м)
Что значит согласованная сущность?
Почему вы решили что это достигается заключением обработки всех строк в одну транзакцию?
Все завсит от поставленной задачи.
Можно условиться так.
В шапке документа ставится пометка что начат резерв (например статус Начато резервирование)
Затем идет резервирование строк, в каждой транзакции обрабатывается Х строк.
В конце переводим статус в шапке "Зарезервировано"
если операция прервана, сервер бд упал, электричество вырубилось итп. В следующий раз мы увидим документ находящийся с большой вероятностью в промежуточном статусе "Начато резервирование". В такой ситуации можно продолжить процесс с того же места. Или если потребуется, запустить откат статуса - снятие резерва.
Зависит от обстоятельств все.
Я недавно, как раз подобную задачу решал.
Идет продажа. При пробитии чека обновляется аналитика "дата пролажи" для товара. И тут выяснилось что все виснет.
Оказывается спецы по олап системе решили раз в месяц закачивать измененные аналитики. Делали это через специальный документ - шапка и строки. В строках аналитика и товар. При утверждении документа, аналитики проливабтся из строк в свойства товаров.
Ну и олапщики закачали 110 тыщ строк в документ и запустили утверждение. На кассе все повисло.
Что тут быстро сделать?
Порезал процесс утверждения на множество транзакций по 50 строк на транзакцию. Все проблемы ушли.
Если утверждение прервалось, можно продолжить с того же места.
Проблема решена.
Это еще вы почему так решили?
Условия могуть быть разными и их определяет бизнес. Я 12 лет проработал в компании дистрибьюторе. Там сеть магазинов, например 7й континет делала регулярно кучу заказов по заказу на магазин. В каждом заказе десятки товаров, обычно от 40 до 100. Заказ можно было отгружать если процент зарезервированных строк был не меньше какого то числа. То ли 60% то ли 70. За давностью лет уже не помню. К тому же заказ делался за несколько дней до отгрузки так что в течение дня попытка резервирования могла повторяться несколько раз (чтобы повысить % резервирования в случае если где то отказались от резерва или новый товар поступил).
Если требования бизнеса такие как вы предполагаете, то нет никакой проблемы снять резерв (можно в блоке catch принять это решение).
Но опять же все зависит от поставленной задачи.
Не понял в чем затруднение.
Движок бд откатит транзакцию так же как и в случае одной транзакции на кучу строк.
Или вас беспокоит в каком статусе получится документ в целом, если в нем по части строк резерв прошел успешно а в части нет?
Так есть же try catch. Ситуация ловится и обрабатывается снова.
Кстати, встречал на практике документы и на 2 - 3 тысячи строк. Когда из магазинов заливали сгруппированные по магазинам данные реализации за весь день.
Встречался на практике с такой проблемой. Обычно помогает разбиение не более короткие транзакции. Ну например если типичный документ содержит 50 строк, то зачем делать резерв в одной транзакции? Можно по транзакции на строку.
У меня Legion 5 21го года. Всем доволен.
Наивно ожидать, что другие мессенджеры так не будут делать, или что их владельцев не прогнут сильные мира сего (Дурова просто так что ли прессовали во франции)
И проверить вы не можете. Косвенно предполагать - да. Но надежнее исходить из самых худших и реалистичных предположений - что все сливается.
Полистал ваш профиль, а там как раз статьи и сравнениеис другими мессенджерами.
Значит перепутал. Сорри