Возник вопрос с транзакциями в джанге.
Есть корзина покупок. Процесс покупки выглядит так:
try:
# оборачиваем всё в транзакцию
with transaction.atomic():
# помечаем товары как купленные
self.cursor.execute("UPDATE public_cars SET status=2, user_id=%s WHERE item_id=%s", [user_id, item_id])
# обновляем баланс покупателя
self.cursor.execute("UPDATE account_myuser SET balance = balance - %s WHERE id=%s", [total_price, user_id])
# получаем текущий баланс
current_balance = self.get_current_balance()
# если баланс стал меньше 0 или равен прошлому балансу - отменяем заказ
if current_balance < 0 or current_balance == balance_before:
# problem!
transaction.rollback()
raise IntegrityError
# сохраняем логи покупки
new_transaction = Transaction(
user=self.user_instance,
amount=total_price,
balance_before=balance_before,
balance_after=current_balance
)
new_transaction.save()
except (IntegrityError, OperationalError), e:
# логируем ошибки
pass
В 99% случаев код работает как задумано. Но по непонятным для меня причинам стали происходить утечки денег.
Удалось отловить один из случаев:
У юзера был баланс 100$
Он приобрел товар за 15$
Товар пометился как купленный, лог покупки записался, а баланс не был изменен!
Причем в логах покупки всё корректно (!)
amount = 15 $
balance_before = 100 $
balance_after = 75 $
Но у юзера баланс остался 100$.
Ошибки не зафиксированы (except не срабатывал).
Как такое возможно?