Lost Update
Потерянное обновление возникает, когда две транзакции читают одно состояние, независимо вычисляют новое, а поздняя запись затирает результат ранней.
Начальное quantity = 10
T1 читает 10 T2 читает 10
T1 пишет 11, commit T2 пишет 11, commit
Итог 11, хотя ожидался 12Решение 1: атомарный UPDATE
Если изменение можно выразить относительно текущего значения, чтение приложению не нужно:
UPDATE inventory
SET quantity = quantity + 1
WHERE sku = 'A-1';СУБД сериализует конфликтующие обновления строки своим механизмом блокировок/версий.
Решение 2: оптимистическая версия
UPDATE orders
SET state = 'PAID',
version = version + 1
WHERE id = 42
AND version = 7
AND state = 'NEW';Если обновлено 0 строк, состояние изменилось конкурентно. Приложение решает: перечитать, вернуть конфликт или безопасно повторить.
Решение 3: пессимистическая блокировка
BEGIN;
SELECT state
FROM orders
WHERE id = 42
FOR UPDATE;
UPDATE orders SET state = 'PAID' WHERE id = 42;
COMMIT;Блокировка нужна до чтения, на котором основано решение. Она повышает ожидания и риск deadlock, поэтому порядок захвата ресурсов должен быть стабильным.
Решение 4: constraint или serializable
Часть инвариантов надежнее выразить ограничением. Для сложных предикатных инвариантов может понадобиться SERIALIZABLE с обработкой serialization failure.
Ловушки
synchronizedзащищает только один процесс приложения.- Проверка версии без анализа количества измененных строк бесполезна.
- Слепой retry может повторно выполнить внешний побочный эффект.
- Высокий уровень изоляции не следует считать универсальной защитой: поведение lost update зависит от реализации.
Связано: Изоляция транзакций, Транзакции принцип ACID, Кейс исключение было проглочено внутри транзакции.
Вопросы
Самое простое решение для счетчика? Атомарный UPDATE counter = counter + ?.
Когда выбирать optimistic locking? Когда конфликты редки и блокировать строку заранее дорого.
Как обнаружить конфликт версии? Проверить, что условный UPDATE изменил ровно одну строку.
Почему локальный lock приложения недостаточен? Есть другие инстансы и внешние клиенты БД.