Транзакции и блокировки - Примеры.

Page / - Изменено Alexandr Fokin в 2024/05/28 20:47

Примеры.

Изменено Alexandr Fokin

в 2024/05/28 20:47

Оглавление

Необходимый уровень изоляции	Запрос	Комментарий
Замечание: в приведенных ниже примерах не рассматриваются сценарии с использованием Оптимистичная блокировка.
READ COMMITTED	BEGIN; UPDATE accounts SET balance = balance + @payment WHERE acctnum = @account1 UPDATE accounts SET balance = balance - @payment WHERE acctnum = @account2 COMMIT;	Относительное изменения значения (а не константное). Без проверок.
REPEATABLE READ	MSSQL SET TRANSACTION ISOLATION LEVEL REPEATABLE READ; BEGIN TRANSACTION if (SELECT balance FROM accounts /*FOR UPDATE*/ where acctnum = @account2 ) < @payment //error END IF UPDATE accounts SET balance = balance + @payment WHERE acctnum = @account1 UPDATE accounts SET balance = balance - @payment WHERE acctnum = @account2 COMMIT; Postgres BEGIN TRANSACTION ISOLATION LEVEL REPEATABLE READ; 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). (Причем для данного примера явная блокировка была бы обязательна только для проверяемого аккаунта, с которого выполняется списание).