Логотип YeaHub

База вопросов

Собеседования

Тренажёр

База ресурсов

Обучение

Навыки

Войти

Выбери, каким будет IT завтра — вместе c нами!

YeaHub — это полностью открытый проект, призванный объединить и улучшить IT-сферу. Наш исходный код доступен для просмотра на GitHub. Дизайн проекта также открыт для ознакомления в Figma.

© 2026 YeaHub

Документы

Медиа

Назад
Вопрос про Postgres: Lost Update, concurrency, transaction isolation, database, optimistic locking, pessimistic locking

Что такое Lost Update и как его избежать?

Вопрос проверяет понимание проблемы Lost Update (потерянного обновления) в конкурентных системах и способов её предотвращения, что критично для обеспечения целостности данных в многопользовательских приложениях и базах данных.

Короткий ответ

Lost Update (потерянное обновление) — это проблема, возникающая при одновременном изменении одних и тех же данных двумя или более транзакциями, когда одно из обновлений теряется, потому что оно перезаписывается другим. Это происходит, если транзакции читают данные, не блокируя их для изменения другими. Чтобы избежать Lost Update, используют механизмы блокировок (пессимистичные или оптимистичные), повышают уровень изоляции транзакций (например, до Repeatable Read или Serializable) или применяют атомарные операции (например, UPDATE с условием).

Длинный ответ

Lost Update (потерянное обновление) — классическая проблема конкурентного доступа в базах данных и многопоточных системах. Она возникает, когда две или более транзакции читают одну и ту же запись, затем независимо её модифицируют и записывают обратно. В результате изменения, сделанные одной из транзакций, могут быть бесследно перезаписаны другой, так как каждая транзакция "не видит" изменений другой до момента коммита.

Как возникает проблема

Рассмотрим типичный сценарий с балансом банковского счёта. Допустим, начальный баланс равен 100.

  1. Транзакция A читает баланс (100).
  2. Транзакция B читает тот же баланс (100).
  3. Транзакция A добавляет 50 и записывает новый баланс (150).
  4. Транзакция B вычитает 20 и записывает новый баланс (80), перезаписывая результат транзакции A.

Итоговый баланс — 80, хотя должен быть 130 (100 + 50 - 20). Обновление от транзакции A потеряно.

Способы предотвращения Lost Update

Существует несколько распространённых подходов:

  • Пессимистичные блокировки (Pessimistic Locking): Транзакция явно блокирует запись на время своего выполнения (например, с помощью SELECT FOR UPDATE в SQL). Другие транзакции ждут снятия блокировки.
  • Оптимистичные блокировки (Optimistic Locking): Используется версионирование записей (например, поле version или timestamp). При обновлении проверяется, что версия не изменилась с момента чтения.
  • Повышение уровня изоляции транзакций: Уровни Repeatable Read или Serializable в большинстве СУБД автоматически предотвращают Lost Update, блокируя чтение-модификацию.
  • Атомарные операции: Выполнение обновления в одном операторе (например, UPDATE accounts SET balance = balance + 50 WHERE id = 1), что исключает промежуточное чтение.

Пример кода (оптимистичная блокировка)

Допустим, у нас есть таблица accounts с полями id, balance и version.

-- Транзакция 1 и 2 читают одну запись
SELECT balance, version FROM accounts WHERE id = 1;
-- Допустим, результат: balance=100, version=1

-- Транзакция 1 пытается обновить
UPDATE accounts 
SET balance = 150, version = version + 1 
WHERE id = 1 AND version = 1;
-- Успешно, если версия не менялась

-- Если транзакция 2 попытается сделать то же с version=1,
-- её UPDATE не затронет строки (0 affected rows),
-- и приложение может повторить операцию с новыми данными.

Вывод: Lost Update — серьёзная угроза целостности данных в системах с высокой конкуренцией. Для её предотвращения необходимо выбирать стратегию блокировок в зависимости от частоты конфликтов: пессимистичные блокировки подходят для частых конфликтов, а оптимистичные — для редких, так как они обеспечивают лучшую производительность за счёт повторных попыток. Уровни изоляции транзакций и атомарные операции — базовые инструменты, которые следует использовать по умолчанию.

Уровень

  • Рейтинг:

    4

  • Сложность:

    5

Навыки

  • Postgres

    Postgres

  • SQL

Ключевые слова

#Lost Update

#concurrency

#transaction isolation

#database

#optimistic locking

#pessimistic locking

Подпишись на Java Developer в телеграм