Возможна гонка check-then-act: несколько узлов увидят один баланс, одобрят покупки и перезапишут друг друга. Нужна атомарная проверка и списание в БД.
Возможные конфликты при одновременном доступе
Возможна гонка check-then-act: несколько узлов увидят один баланс, одобрят покупки и перезапишут друг друга. Нужна атомарная проверка и списание в БД.
Короткий ответ
Что ответить на собеседовании
Подробный разбор
Ответ с пояснениями
Условие
Опишите, какие проблемы могут возникнуть при выполнении следующего псевдокода одновременно на нескольких узлах (синхронно), реализующего процесс покупки мороженого.
balance = get_balance(user_id)
if balance >= ice_cream_price:
balance = balance - ice_cream_price
update_balance(user_id, balance)
Ответ
Возможна гонка check-then-act: несколько узлов увидят один баланс, одобрят покупки и перезапишут друг друга. Нужна атомарная проверка и списание в БД.
Например, при балансе 100 и цене 80 два запроса могут оба прочитать 100 и оба записать 20, хотя одобрены две покупки.
UPDATE accounts
SET balance = balance - :price
WHERE user_id = :user_id AND balance >= :price;
Успех определяется числом обновлённых строк. Цена должна быть проверенной положительной суммой в целых минимальных денежных единицах. Создание заказа и списание включают в одну транзакцию; повтор запроса защищают уникальным ключом идемпотентности. Альтернатива — блокировка строки через SELECT FOR UPDATE. Локальный mutex одного процесса не защищает от конкурентных запросов на других узлах.