Вы только что обнаружили, почему финансовые операции сложны: -)
Задумывались ли вы, почему вам требуется время для обновления баланса на вашем банковском счете? Или почему у вас два баланса вместо одного?
Это потому, что ваша учетная запись может на самом деле стать отрицательной и (до определенного момента), что будет хорошо.
Таким образом, в сценарии реальной жизни получается, что у вас есть баланс 100 $, вы платите 10 $, и до тех пор, пока получатель не обработает и не подтвердит эту транзакцию, у вас останутся ваши 100 $. Если вы совершите 20 транзакций по 10 $ каждая, вы сможете их завершить, потому что система, скорее всего, не сможет это заметить.
И, честно говоря, не должно. Подумайте о кредитных картах, у вас сейчас может не хватить денег, но, может быть, вы знаете, что у вас будет достаточно денег в срок.
Итак, условие гонки, которое вы описываете, работает, только если вы действительно прочитали значение и затем обновили его.
Есть несколько подходов:
- Считать текущий баланс и обновить строку, используя старый баланс в качестве поля в операторе where. Таким образом, если он не обновляет строки, вы знаете, что вам нужно перечитать и обновить.
- Не обновляйте баланс и делайте это только по времени, скажем, раз в час. Да, возможно, вам еще придется выполнить некоторые проверки, но система в целом будет более отзывчивой.
- Заблокируйте строку базы данных в качестве первого шага. Это бы сработало, но есть вероятность, что оно замедлит работу приложения.