Примеры.

Версия 1.17 от Alexandr Fokin на 2023/02/25 15:08

Необходимый уровень изоляцииЗапросКомментарий
READ COMMITTEDBEGIN;

UPDATE accounts
SET balance = balance + @payment
WHERE acctnum = @account1

UPDATE accounts
SET balance = balance - @payment
WHERE acctnum = @account2

COMMIT;
  • Относительное изменения значения (а не константное).
  • Без проверок.
REPEATABLE READBEGIN;

 if (SELECT balance FROM accounts where acctnum = @account2) < @payment
   RAISE EXCEPTION ''
 END IF

UPDATE accounts
SET balance = balance + @payment
WHERE acctnum = @account1

UPDATE accounts
SET balance = balance - @payment
WHERE acctnum = @account2

COMMIT;
  • Предварительная проверка условия перед изменением строк.
    Гарантия, что значение не будет изменено другими транзакциями после проверки (или их изменение будет обнаружено и приведет к ошибке).
  • В запросе могут использоваться как относительные, так и константные значения, при условии что значение было сформировано после проверки допустимости операции.

Данное поведение также может быть реализовано на уровне READ COMMITTED, но для этого нужно использовать механизм явных блокировок (обычно это что-то вроде UPDLOCK).
(Причем для данного примера явная блокировка была бы обязательна только для проверяемого аккаунта, с которого выполняется списание).