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

Версия 1.33 от Alexandr Fokin на 2025/09/20 11:03

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