В данной задаче правильно будет использовать уровень изоляций БД READ_COMMITED?
Задача: При обращений к апи нужно оформить подписку пользователю выполнив бизнес логику для этого.
Алгоритм:
1. Принять запрос
2. Получить прайс подписки
3. Проверить баланс пользователя
4. Вычесть баланс
5. Выдать подписку
Как я понял транзакций сначала выполняются и при успехе делают изменения в бд. Я вот думаю вот если как то очень быстро выполнить несколько запросов, соответственно каждый запрос будет обрабатывать этот алгоритм. И пока 1-ый запрос с транзакций еще выполняется и вычитает баланс, то 2-ой запрос может быть еще не видит эти изменения и думает что у пользователя баланс есть и снова выдает ему подписку. По сути нужно использовать для такого случая уровень изоляций READ_COMMITED, чтобы транзакций в реальном времени видели что там у них внутри изменилось уже?
Akina, транзакция нужна, пример, в момент выдачи подписки, что-то сломалось, без общей транзакции, у пользователя произойдет списание, но подписку он не получит
Dr. Bacon, распиши всё то же на три части, что происходит 1) в коде интерфейсе пользователя 2) в клиентском коде веб-сервера 3) на SQL-сервере. И твой пункт 5 развалится на три подпункта, причём пункт 5а выполняется на SQL-сервере и составляет единое целое с пунктами 2, 3 и 4, а не отдельные пункты, как написано в вопросе.
Впрочем, я не заставляю дискутировать. Есть желание наворотить транзакции, и для этого написать кучу никому не нужного кода, требующего к тому же кучу столь же ненужного дополнительного кода со всякими необходимыми проверками - да пожалуйста, мне-то что.
Akina, ага, конечно можно додумать как у ТС реализована подписка, и да, в простейшем случае, это может быть даже поле в той же таблице, где и баланс, но если это разные таблицы, то получаем, что мы перенесли часть бизнес логики на уровень SQL-сервера, это очень "веселое" решение, так размазать бизнес логику по разным слоям.
получаем, что мы перенесли часть бизнес логики на уровень SQL-сервера, это очень "веселое" решение, так размазать бизнес логику по разным слоям
Ааа... вот оно об чём. Ну да. Сейчас это общая проблема, ни одна надстройка не желает работать на стороне SQL, ибо просто не умеет. Медленно и так себе эффективно? какая ерунда! зато логика вся в одном месте.
Dr. Bacon, Работает! Правда с таймаутами поигрался, и остальным запросам придется ждать пока 1-ый выполнится это может и 10 секунд (для примера поставил), но как я понял в этом и заключается суть.
HCEL, Откуда 10сек? Это очень долго, "и остальным запросам придется" ты там всю таблицу что ли лочишь? Надо лочить только одну конкретную запись, которую собрался изменять
Dr. Bacon, Все норм одну запись локаю вот так SELECT * WHERE `User`.`id` = 8 FOR UPDATE; Я просто специально поставил тайм аут в 10 секунд, чтобы посмотреть как остальные параллельные запросы отработают (Те же запросы на обновление баланса). Они все ждут т.е так и должно работать как я понял.