1) Использовать уровень изоляции транзакций: serializable
но производительность Update упадет, поэтому лучше делать замеры и смотреть, подходит или нет. Обычно Update-ов не так много как чтений.
Преимущество: не надо будет танцевать с бубном.
2) Сделать эту операцию через класс, который контролирует. Т.е. если мы делаем запрос второй раз, это класс смотрит, завершился ли первый.
А тут уже 2 варианта:
- ответить пользователю отказом (типо: "дождитесь окончания предыдущей операции")
- дождаться выполнения первой и приступить к выполнению второй. Но если после первой, баланс <0, то сказать об этом пользователю.