Вступить в клуб →
сложнаявопросSQL и оптимизация запросов

Два одновременных списания: потерянное обновление баланса

Списание средств реализовано так:

var acc = await db.Accounts.FirstAsync(a => a.Id == id);
acc.Balance -= amount;
await db.SaveChangesAsync();

Баланс 1000. Пришли два параллельных запроса на списание по 100 каждый, оба успели прочитать строку до того, как любой из них сохранил изменения. В базе оказалось 900.

Как корректно устранить проблему?

  • Достаточно обернуть код в транзакцию: сама транзакция не даст двум запросам одновременно прочитать и изменить одну строку, второй дождётся первого
  • Выполнять вычитание атомарно на стороне базы, блокировать строку при чтении или добавить токен параллелизма
  • Ничего делать не нужно: EF Core сам обнаружит конфликт и выбросит DbUpdateConcurrencyException
  • Перечитывать сущность прямо перед SaveChanges — тогда второй запрос увидит уже изменённый баланс

🔒 Проверка ответа — для участников клуба

  • Проверка ответа
  • Подсказка, если застряли
  • Разбор с объяснением, почему так
  • Прогресс по всем задачам и виртуальные собеседования
Зарегистрироваться →

Регистрация занимает минуту

Другие задачи раздела