Проиллюстрируем нежелательные эффекты, возникающие при параллельном выполнении транзакций на примере таблицы
EXAMPLE
. Мы предполагаем, что в начале выполнения каждого следующего пункта содержимое этой таблицы возвращается к исходному, а именно:
Таблица EXAMPLE
id INTEGER | dat INTEGER |
1 | 100 |
2 | 110 |
3 | 120 |
4 | 130 |
5.3.1 Потерянные изменения
Транзакция T1 | Шаг | Транзакция T2 |
UPDATE example SET dat=dat+1 WHERE id=1 | 1 | |
| 2 | UPDATE example SET dat=dat+1 WHERE id=1 |
COMMIT | 3 | |
| 4 | COMMIT |
SELECT * FROM example | 5 | |
Если потерянные изменения допускаются, то сценарий выполнится без ошибок и блокировок. На шаге 5 будет выбрано:
id dat
---------- -----------
1 101
2 110
3 120
4 130
5.3.2 Грязное чтение
Транзакция T1 | Шаг | Транзакция T2 |
| 1 | UPDATE example SET dat=101 WHERE id=1 |
UPDATE example SET dat= (SELECT dat FROM example WHERE id=1) WHERE id=2 | 2 | |
SELECT * FROM example | 3 | |
| 4 | ROLLBACK |
| 5 | SELECT * FROM example |
Если грязное чтение допускается, то сценарий выполнится без ошибок и блокировок.
На шаге 3 будет выбрано:
id dat
---------- -----------
1 101
2 101
3 120
4 130
На шаге 5 будет выбрано:
id dat
---------- -----------
1 100
2 101
3 120
4 130
5.3.3 Неповторяющееся чтение
Транзакция T1 | Шаг | Транзакция T2 |
SELECT * FROM example WHERE id=1 | 1 | |
[COMMIT] | 2 | UPDATE example SET dat=101 WHERE id=1 |
| 3 | COMMIT |
SELECT * FROM example WHERE id=1 | 4 | |
COMMIT | 5 | |
Если неповторяющееся чтение допускается, то сценарий выполнится без ошибок и блокировок. Операцию
COMMIT
в транзакции T1 на шаге 2 выполнять не придется.
На шаге 1 будет выбрано:
id dat
---------- -----------
1 100
На шаге 4 будет выбрано:
id dat
---------- -----------
1 101
Если выполнить операцию COMMIT
на шаге 2, то результаты будут те же, что и без нее, но здесь уже не будет эффекта неповторяющегося чтения, так как разные результаты будут прочитаны уже в разных транзакциях.
Транзакция T1 | Шаг | Транзакция T2 |
SELECT * FROM example WHERE dat>110 | 1 | |
[COMMIT] | 2 | INSERT INTO example VALUES(5,140) |
| 3 | COMMIT |
SELECT * FROM example WHERE dat>110 | 4 | |
COMMIT | 5 | |
Если допускаются фантомы, то сценарий выполнится без ошибок и блокировок. Операцию
COMMIT
в транзакции T1 на шаге 2 выполнять не придется.
На шаге 1 будет выбрано:
id dat
---------- -----------
3 120
4 130
На шаге 4 будет выбрано:
id dat
---------- -----------
3 120
4 130
5 150
Немає коментарів:
Дописати коментар