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

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

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