Sobes.tech
Назад к вопросам
Senior
3

Две параллельные транзакции обновляют одну строку (списание и начисление) — нужно ли что-то сделать? Проблема lost update.

Компании, где спрашивали
ТБанк

Ответ от нейросети

sobes.tech AI

Проблема lost update возникает, когда две параллельные транзакции читают одну и ту же строку, изменяют её и записывают обратно, при этом одна из изменений теряется.

Чтобы избежать этой проблемы, нужно обеспечить правильную изоляцию транзакций и синхронизацию обновлений. Основные подходы:

  1. Использование блокировок (pessimistic locking):

    • При чтении строки ставится блокировка, которая не позволяет другим транзакциям изменять её до завершения текущей.
    • Например, SELECT ... FOR UPDATE в SQL.
  2. Оптимистичная блокировка (optimistic locking):

    • В таблицу добавляется версия или timestamp.
    • При обновлении проверяется, что версия не изменилась с момента чтения.
    • Если изменилась — транзакция откатывается или повторяется.
  3. Правильный уровень изоляции транзакций:

    • Уровень SERIALIZABLE гарантирует последовательное выполнение транзакций, но может снижать производительность.
  4. Использование атомарных операций:

    • Например, обновление с помощью SQL UPDATE ... SET value = value + ? без предварительного чтения.

Пример оптимистичной блокировки:

// Предположим, есть поле version в таблице
// Читаем строку с версией
SELECT balance, version FROM accounts WHERE id = ?;

// При обновлении
UPDATE accounts SET balance = ?, version = version + 1 WHERE id = ? AND version = ?;

// Если affected rows == 0, значит версия изменилась — нужно повторить операцию

Таким образом, чтобы избежать lost update, нужно использовать либо блокировки, либо оптимистичные механизмы контроля версий.