Выбор ответа Middle Транзакции и изоляция спрашивают часто обновлено

Потерянное обновление

Вопрос

Две транзакции в Read Committed одновременно выполняют этот код для одного счёта с балансом 100. Сколько будет на счёте в итоге?

-- в приложении:
BEGIN;
SELECT balance FROM accounts WHERE id = 1;   -- получили 100
-- новый баланс = 100 - 30 = 70
UPDATE accounts SET balance = 70 WHERE id = 1;
COMMIT;

Попробуйте сами

Выберите вариант, и откроется разбор.

Показать ответ и разбор

Коротко

Правильный ответ: 70: обе прочитали 100 и записали 70. Это lost update: обе прочитали 100, записали 70, и одно списание потерялось.

Варианты ответа

  1. 40: база выполнит транзакции строго по очереди
  2. Одна из транзакций упадёт с ошибкой сериализации
  3. 70: обе прочитали 100 и записали 70правильный ответ
  4. 100: обе транзакции откатятся из-за конфликта

Разбор

Это lost update: обе прочитали 100, записали 70, и одно списание потерялось. В Read Committed чтение не ставит блокировку, обе транзакции видят 100, считают в приложении 70 и записывают; второй UPDATE дождётся первого и просто перезапишет значение. Ошибка сериализации возникла бы на Repeatable Read или Serializable. Исправления: атомарный UPDATE ... SET balance = balance - 30, SELECT ... FOR UPDATE или оптимистичная блокировка с версией.

Ответьте сами, а не прочитайте

В тренажёре вопрос попадёт в повторения и вернётся, когда начнёт забываться. Плюс билеты с зачётом: 20 вопросов, не больше 2 ошибок.

Термины по теме