Исходный код вики Примеры.

Версия 1.32 от Alexandr Fokin на 2025/09/19 15:03

Скрыть последних авторов
Alexandr Fokin 1.10 1 (% style="width:1426px" %)
2 |(% style="width:155px" %)**Необходимый уровень изоляции**|(% style="width:614px" %)**Запрос**|(% style="width:652px" %)**Комментарий**
Alexandr Fokin 1.18 3 |(% style="width:155px" %) |(% style="width:614px" %) |(% style="width:652px" %)Замечание: в приведенных ниже примерах не рассматриваются сценарии с использованием [[Оптимистичная блокировка>>doc:Архитектура и модели.Блокировки.Оптимистичная блокировка.WebHome]].
Alexandr Fokin 1.9 4 |(% style="width:155px" %)READ COMMITTED|(% style="width:614px" %){{code language="sql"}}BEGIN;
Alexandr Fokin 1.1 5
Alexandr Fokin 1.2 6 UPDATE accounts
7 SET balance = balance + @payment
8 WHERE acctnum = @account1
Alexandr Fokin 1.1 9
Alexandr Fokin 1.2 10 UPDATE accounts
11 SET balance = balance - @payment
Alexandr Fokin 1.11 12 WHERE acctnum = @account2
Alexandr Fokin 1.1 13
Alexandr Fokin 1.10 14 COMMIT;{{/code}}|(% style="width:652px" %)(((
Alexandr Fokin 1.7 15 * Относительное изменения значения (а не константное).
16 * Без проверок.
Alexandr Fokin 1.32 17
18 (В данном случае строка заблокируется в момент обновления, чтение (select) с проверкой без явного указания updlock, то строка может быть изменена после проверки условия).
Alexandr Fokin 1.7 19 )))
Alexandr Fokin 1.26 20 |(% style="width:155px" %)REPEATABLE READ|(% style="width:614px" %)(((
Alexandr Fokin 1.29 21 |MSSQL|{{code language="sql"}}SET TRANSACTION ISOLATION LEVEL REPEATABLE READ;
22 BEGIN TRANSACTION
Alexandr Fokin 1.2 23
Alexandr Fokin 1.29 24 if (SELECT balance FROM accounts /*FOR UPDATE*/ where acctnum = @account2 ) < @payment
Alexandr Fokin 1.26 25 //error
26 END IF
27
28 UPDATE accounts
29 SET balance = balance + @payment
30 WHERE acctnum = @account1
31
32 UPDATE accounts
33 SET balance = balance - @payment
34 WHERE acctnum = @account2
35
36 COMMIT;{{/code}}|
Alexandr Fokin 1.30 37 |Postgres|{{code language="sql"}}BEGIN TRANSACTION ISOLATION LEVEL REPEATABLE READ;
Alexandr Fokin 1.26 38
39 if (SELECT balance FROM accounts where acctnum = @account2 ) < @payment
Alexandr Fokin 1.1 40 RAISE EXCEPTION ''
41 END IF
42
Alexandr Fokin 1.2 43 UPDATE accounts
44 SET balance = balance + @payment
45 WHERE acctnum = @account1
Alexandr Fokin 1.1 46
Alexandr Fokin 1.2 47 UPDATE accounts
48 SET balance = balance - @payment
Alexandr Fokin 1.11 49 WHERE acctnum = @account2
Alexandr Fokin 1.1 50
Alexandr Fokin 1.26 51 COMMIT;{{/code}}|
52 | | |
53 )))|(% style="width:652px" %)(((
Alexandr Fokin 1.7 54 * Предварительная проверка условия перед изменением строк.
Alexandr Fokin 1.14 55 Гарантия, что значение не будет изменено другими транзакциями после проверки (или их изменение будет обнаружено и приведет к ошибке).
56 * В запросе могут использоваться как относительные, так и константные значения, при условии что значение было сформировано после проверки допустимости операции.
Alexandr Fokin 1.15 57
Alexandr Fokin 1.32 58 (В данном случае чтение (select) накладывает share блокировку, что гарантирует, что строка не будет изменена).
59
Alexandr Fokin 1.15 60 ----
61
62 Данное поведение также может быть реализовано на уровне READ COMMITTED, но для этого нужно использовать механизм явных блокировок (обычно это что-то вроде UPDLOCK).
Alexandr Fokin 1.17 63 (Причем для данного примера явная блокировка была бы обязательна только для проверяемого аккаунта, с которого выполняется списание).
Alexandr Fokin 1.7 64 )))