Бази даних-20210115T104840Z-001 / Реферат на тему _Современные СУБД_ / Using_MySql,_MS_SQL_Server_and_Oracle
.pdfПример 44: взаимодействие конкурирующих транзакций
|
A: REPEATABLE READ |
B: READ COMMITTED |
Tr |
A ID = 153 |
Tr B ID = 154 |
Tr |
A START:20:25:29 in REPEATABLE-READ |
Tr B START: 20:25:29 in READ-COMMITTED |
Tr |
A UPDATE:20:25:34 |
Tr B SELECT-1: 20:25:29 |
Tr |
A COMMIT:20:25:34 |
sb_is_active = Y |
|
|
Tr B SELECT-2: 20:25:39 |
|
|
sb_is_active = N |
|
|
Tr B COMMIT: 20:25:39 |
|
|
|
|
A: REPEATABLE READ |
B: REPEATABLE READ |
Tr |
A ID = 156 |
Tr B ID = 155 |
Tr |
A START:20:26:24 in REPEATABLE-READ |
Tr B START: 20:26:24 in REPEATABLE-READ |
Tr |
A UPDATE:20:26:29 |
Tr B SELECT-1: 20:26:24 |
Tr |
A COMMIT:20:26:29 |
sb_is_active = N |
|
|
Tr B SELECT-2: 20:26:34 |
|
|
sb_is_active = N |
|
|
Tr B COMMIT: 20:26:34 |
|
|
|
|
|
A: REPEATABLE READ |
|
|
|
B: SERIALIZABLE |
||
Tr |
A ID = 157 |
|
|
|
Tr B ID = 158 |
|
||
Tr |
A START:20:27:15 in REPEATABLE-READ |
|
Tr B START: 20:27:15 in SERIALIZABLE |
|||||
Tr |
A UPDATE:20:27:20 |
|
|
|
Tr B SELECT-1: 20:27:15 |
|||
Tr |
A COMMIT:20:27:25 |
|
|
|
sb_is_active = Y |
|
||
|
|
|
|
|
|
Tr B SELECT-2: 20:27:25 |
||
|
|
|
|
|
|
sb_is_active = Y |
|
|
|
|
|
|
|
|
Tr B COMMIT: 20:27:25 |
|
|
|
|
|
|
|
|
|
|
|
|
|
Итоговые результаты взаимодействия транзакций таковы. |
||||||
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Уровень изолированности транзакции B |
|||
|
|
|
READ |
|
READ |
REPEATABLE |
SERIALIZABLE |
|
|
|
|
UNCOMMITTED |
|
COMMITTED |
READ |
||
|
|
|
|
|
||||
|
|
|
|
|
|
|
||
|
|
|
Первый и второй |
Первый и второй |
Первый и второй |
Первый и второй SELECT |
||
|
A |
READ |
SELECT |
|
SELECT |
SELECT возвра- |
возвратили одинаковые |
|
|
транзакции |
|
||||||
|
UNCOMMITTED |
возвратили |
|
возвратили |
тили одинаковые |
данные,транзакция A ждёт |
||
|
|
|
||||||
|
|
|
разные данные |
разные данные |
данные |
завершения B |
||
|
|
|
|
|
|
|
||
|
|
|
Первый и второй |
Первый и второй |
Первый и второй |
Первый и второй SELECT |
||
|
изолированности |
READ |
SELECT |
|
SELECT |
SELECT возвра- |
возвратили одинаковые |
|
|
COMMITTED |
разные данные |
разные данные |
данные |
завершения B |
|||
|
|
возвратили |
|
возвратили |
тили одинаковые |
данные, транзакция A ждёт |
||
|
|
|
разные данные |
разные данные |
данные |
завершения B |
||
|
|
|
Первый и второй |
Первый и второй |
Первый и второй |
Первый и второй SELECT |
||
|
|
REPEATABLE |
SELECT |
|
SELECT |
SELECT возвра- |
возвратили одинаковые |
|
|
|
READ |
возвратили |
|
возвратили |
тили одинаковые |
данные, транзакция A ждёт |
|
|
Уровень |
|
|
|
|
|
|
|
|
|
Первый и второй |
Первый и второй |
Первый и второй |
Первый и второй SELECT |
|||
|
|
|
||||||
|
|
SERIALIZABLE |
SELECT |
|
SELECT |
SELECT возвра- |
возвратили одинаковые |
|
|
|
возвратили |
|
возвратили |
тили одинаковые |
данные, транзакция A ждёт |
||
|
|
|
|
|||||
|
|
|
разные данные |
разные данные |
данные |
завершения B |
||
|
|
|
|
|
|
|
|
|
Чтобы получить другой вариант поведения СУБД, необходимо явно блокиро-
вать читаемые записи (SELECT ... LOCK IN SHARE MODE или SELECT ... FOR UPDATE)37 в первой операции чтения. В данном случае это не было сделано, чтобы
продемонстрировать наиболее типичное поведение MySQL. Проверить же остальные случаи реакции СУБД вам предлагается самостоятельно в задании
6.2.2. TSK.D{464}.
37 http://dev.mysql.com/doc/refman/5.6/en/innodb-locking-reads.html
Работа с MySQL, MS SQL Server и Oracle в примерах © EPAM Systems, RD Dep, 2016-2018 Стр: 470/545
Пример 44: взаимодействие конкурирующих транзакций
Фантомное чтение в MySQL может быть исследовано выполнением в двух отдельных сессиях следующих блоков кода:
MySQL |
|
Решение 6.2.2.a (код для исследования аномалии фантомного чтения) |
|
||||
1 |
-- Транзакция A: |
-- Транзакция B: |
|||||
2 |
SELECT CONCAT('Tr A ID = ', |
SELECT CONCAT('Tr B ID = ', |
|||||
3 |
|
|
|
CONNECTION_ID()); |
|
|
CONNECTION_ID()); |
4 |
SET autocommit = 0; |
SET autocommit = 0; |
|||||
5 |
SET SESSION TRANSACTION |
SET SESSION TRANSACTION |
|||||
|
ISOLATION LEVEL {УРОВЕНЬ}; |
ISOLATION LEVEL {УРОВЕНЬ}; |
|||||
|
START TRANSACTION; |
START TRANSACTION; |
|||||
8 |
SELECT CONCAT('Tr A START: ', |
SELECT CONCAT('Tr B START : ', |
|||||
9 |
|
|
|
CURTIME(), ' in '); |
|
|
CURTIME(), ' in '); |
10 |
SELECT |
'VARIABLE_VALUE' |
SELECT 'VARIABLE_VALUE' |
||||
11 |
FROM |
|
'information_schema' |
FROM |
'information_schema' |
||
12 |
|
|
|
'session_variables' |
|
'session_variables' |
|
13 |
WHERE |
'VARIABLE_NAME' = |
WHERE |
'VARIABLE_NAME' = |
|||
14 |
|
|
|
'tx isolation'; |
|
'tx isolation'; |
|
15 |
|
|
|
|
SELECT CONCAT('Tr B COUNT-1: ', |
||
16 |
|
|
|
|
|
|
CURTIME()); |
17 |
SELECT SLEEP(5); |
SELECT COUNT(*) |
|||||
18 |
|
|
|
|
FROM |
'subscriptions' |
|
19 |
|
|
|
|
WHERE |
'sb id' > 5001 |
|
|
SELECT CONCAT('Tr A INSERT: ', |
|
|
|
|||
21 |
|
|
|
CURTIME()); |
|
|
|
22 |
INSERT INTO 'subscriptions' |
|
|
|
|||
23 |
|
|
|
('sb_id', |
|
|
|
24 |
|
|
|
'sb_subscriber', |
|
|
|
25 |
|
|
|
'sb_book', |
|
|
|
26 |
|
|
|
'sb_start', |
|
|
|
27 |
|
|
|
'sb_finish', |
SELECT SLEEPi10>; |
||
28 |
|
|
|
'sb_is_active') |
|
|
|
29 |
|
|
VALUES (1000, |
|
|
|
|
30 |
|
|
|
1, |
|
|
|
31 |
|
|
|
1, |
|
|
|
32 |
|
|
|
'2025-01-12', |
|
|
|
33 |
|
|
|
'2026-02-12', |
|
|
|
34 |
|
|
|
'N'); |
|
|
|
|
|
|
|
|
|
||
35 |
|
|
|
|
SELECT CONCAT('Tr B COUNT-2: ', |
||
36 |
SELECT SLEEP(10 ; |
|
|
CURTIME()); |
|||
37 |
|
|
|
|
SELECT COUNT(*) |
||
38 |
|
|
|
|
FROM |
'subscriptions' |
|
39 |
|
|
|
|
WHERE |
'sb id' > 5001 |
|
|
SELECT CONCAT('Tr A ROLLBACK: ', 41 |
SELECT SLEEP(15); |
|||||
|
|
|
|
CURTIME()); |
|
|
|
|
ROLLBACK; |
|
|
|
|||
|
|
|
|
|
|
||
43 |
|
|
|
|
SELECT CONCAT('Tr B COUNT-3: ', |
||
44 |
|
|
|
|
|
|
CURTIME()); |
45 |
|
|
|
|
SELECT COUNT(*) |
||
46 |
|
|
|
|
FROM |
'subscriptions' |
|
47 |
|
|
|
|
WHERE |
'sb_id' > 5001 |
|
48 |
|
|
|
|
SELECT CONCAT('Tr B COMMIT: ', |
||
49 |
|
|
|
|
|
|
CURTIME()); |
50 |
|
|
|
|
COMMIT; |
|
|
Приведём пример журнала выполнения этого кода для ситуации, когда транзакция A выполняется на уровне изолированности SERIALIZABLE и конкурирует с
транзакцией B, последовательно выполняемой во всех поддерживаемых MySQL уровнях изолированности.
Работа с MySQL, MS SQL Server и Oracle в примерах © EPAM Systems, RD Dep, 2016-2018 Стр: 471/545
Пример 44: взаимодействие конкурирующих транзакций
|
A: SERIALIZABLE |
B: READ UNCOMMITTED |
Tr A ID = 198 |
Tr B ID = 197 |
|
Tr |
A START: 21:08:32 in SERIALIZABLE |
Tr B START: 21:08:32 in READ-UNCOMMITTED |
Tr |
A INSERT: 21:08:37 |
Tr B COUNT-1: 21:08:32 |
Tr |
A ROLLBACK: 21:08:47 |
COUNT(*) = 0 |
|
|
Tr B COUNT-2: 21:08:42 |
|
|
COUNT(*) = 1 |
|
|
Tr B COOUNT-3:21:08:57 |
|
|
COUNT(*) = 0 |
|
|
Tr B COMMIT: 21:08:57 |
|
A: SERIALIZABLE |
B: READ COMMITTED |
Tr A ID = 200 |
Tr B ID = 199 |
|
Tr |
A START: 21:09:34 in SERIALIZABLE |
Tr B START: 21:09:34 in READ-COMMITTED |
Tr |
A INSERT: 21:09:39 |
Tr B COUNT-1: 21:09:34 |
Tr |
A ROLLBACK: 21:09:49 |
COUNT(*) = 0 |
|
|
Tr B COUNT-2: 21:09:44 |
|
|
COUNT(*) = 0 |
|
|
Tr B COUNT-3: 21:09:59 |
|
|
COUNT(*) = 0 |
|
|
Tr B COMMIT: 21:09:59 |
|
|
|
|
A: SERIALIZABLE |
B: REPEATABLE READ |
Tr A ID = 201 |
Tr B ID = 202 |
|
Tr |
A START: 21:10:28 in SERIALIZABLE |
Tr B START: 21:10:28 in REPEATABLE-READ |
Tr |
A INSERT: 21:10:33 |
Tr B COUNT-1: 21:10:28 |
Tr |
A ROLLBACK: 21:10:43 |
COUNT(*) = 0 |
|
|
Tr B COUNT-2: 21:10:38 |
|
|
COUNT(*) = 0 |
|
|
Tr B COUNT-3: 21:10:53 |
|
|
COUNT(*) = 0 |
|
|
Tr B COMMIT: 21:10:53 |
|
|
|
|
|
A: SERIALIZABLE |
|
|
B: SERIALIZABLE |
||
Tr A ID = 203 |
|
|
Tr B ID = 204 |
|
|||
Tr |
A START: 21:11:29 in SERIALIZABLE |
|
Tr B START: 21:11:29 in SERIALIZABLE |
||||
Tr |
A INSERT: 21:11:34 |
|
|
Tr B COUNT-1: 21:11:29 |
|
||
Tr |
A ROLLBACK: 21:11:44 |
|
COUNT(*) = 0 |
|
|||
|
|
|
|
|
Tr B COUNT-2: 21:11:39 |
|
|
|
|
|
|
|
COUNT(*) = 0 |
|
|
|
|
|
|
|
Tr B COUNT-3: 21:11:59 |
|
|
|
|
|
|
|
COUNT(*) = 0 |
|
|
|
|
|
|
|
Tr B COMMIT: 21:11:59 |
|
|
|
|
Итоговые результаты взаимодействия транзакций таковы. |
|||||
|
|
|
|
|
|
|
|
|
|
|
|
Уровень изолированности транзакции B |
|||
|
|
|
READ |
READ COMMITTED |
REPEATABLE |
SERIALIZABLE |
|
|
|
|
UNCOMMITTED |
READ |
|||
|
|
|
|
|
|
||
|
|
|
|
|
|
|
|
|
|
|
Транзакция B |
Транзакция B не |
Транзакция B не |
Транзакция B не получает |
|
|
A |
READ |
успевает обра- |
получает доступа к |
получает доступа |
доступа к «фантомной за- |
|
|
транзакции |
||||||
|
UNCOMMITTED |
ботать «фан- |
«фантомной |
к «фантомной |
писи», COUNT-3 ждёт за- |
||
|
|
||||||
|
|
|
томную запись» |
записи» |
записи» |
вершения транзакции A |
|
|
|
|
|
|
|
|
|
|
|
|
Транзакция B |
Транзакция B не |
Транзакция B не |
Транзакция B не получает |
|
|
изолированности |
READ |
успевает обра- |
получает доступа к |
получает доступа |
доступа к «фантомной за- |
|
|
COMMITTED |
томную запись» |
записи» |
записи» |
вершения транзакции A |
||
|
|
ботать «фан- |
«фантомной |
к «фантомной |
писи», COUNT-3 ждёт за- |
||
|
|
|
томную запись» |
записи» |
записи» |
вершения транзакции A |
|
|
|
|
Транзакция B |
Транзакция B не |
Транзакция B не |
Транзакция B не получает |
|
|
|
REPEATABLE |
успевает обра- |
получает доступа к |
получает доступа |
доступа к «фантомной за- |
|
|
|
READ |
ботать «фан- |
«фантомной |
к «фантомной |
писи», COUNT-3 ждёт за- |
|
|
Уровень |
|
|
|
|
|
|
|
|
Транзакция B |
Транзакция B не |
Транзакция B не |
Транзакция B не получает |
||
|
|
|
|||||
|
|
SERIALIZABLE |
успевает обра- |
получает доступа к |
получает доступа |
доступа к «фантомной за- |
|
|
|
ботать «фан- |
«фантомной |
к «фантомной |
писи», COUNT-3 ждёт за- |
||
|
|
|
|||||
|
|
|
томную запись» |
записи» |
записи» |
вершения транзакции A |
|
|
|
|
|
|
|
|
|
На этом решение для MySQL завершено.
Работа с MySQL, MS SQL Server и Oracle в примерах © EPAM Systems, RD Dep, 2016-2018 Стр: 472/545
Пример 44: взаимодействие конкурирующих транзакций
Переходим к MS SQL Server. Данная СУБД поддерживает пять уровней изолированности транзакций, комбинации которых мы и рассмотрим:
•READ UNCOMMITTED;
•READ COMMITTED;
•REPEATABLE READ;
•SNAPSHOT;
•SERIALIZABLE.
Для выполнения эксперимента используем командный файл:
start cmd.exe /с "sqlcmd -S КОМПЬЮТЕР\СЕРВЕР -i a.sql & pause" start cmd.exe /c "sqlcmd -S КОМПЬЮТЕР\СЕРВЕР -i b.sql & pause"
Для упрощения кода приведённых далее запросов создадим функции GET_ISOLATION_LEVEL и GET_CT, возвращающие, соответственно, значение текущего уровня изолированности транзакции и значение текущего времени.
MS SQL I |
Решение 6.2.2.a (код и запрос для проверки работоспособности сервисных функций) |
| |
1CREATE FUNCTION GET ISOLATION LEVEL()
2RETURNS NVARCHAR 50
3BEGIN
4DECLARE @IsolationLevel NVARCHAR'50);
5SET @IsolationLevel = (
6SELECT CASE [transaction isolation level]
7WHEN 0 THEN 'Unspecified'
8WHEN 1 THEN 'Read Uncommitted'
9WHEN 2 THEN 'Read Committed'
10WHEN 3 THEN 'Repeatable Read'
11WHEN 4 THEN 'Serializable'
12WHEN 5 THEN 'Snapshot' END AS TRANSACTION ISOLATION LEVEL
13FROM [sys] [dm exec sessions]
14WHERE [session id] = @@SPID);
15RETURN @IsolationLevel
16END;
17GO
18
19CREATE FUNCTION GET CT()
20RETURNS NVARCHAR 50
21BEGIN
22DECLARE @CT NVARCHAR 50);
23SET @CT = CONVERT(NVARCHAR 12 , GETDATE(), 114);
24RETURN @CT
25END;
26GO
27
28PRINT dbo.GET ISOLATION LEVEL();
29PRINT dbo.GET CT() ;
Обратите внимание на два важных момента:
•для обеспечения работоспособности уровня изолированности транзакции
SNAPSHOT необходимо выполнить команду ALTER |
DATABASE |
[имя_баЗы_данных] SET ALLOW_SNAPSHOT_ISOLATION ON; |
|
•в представленном ниже коде мы будем дважды подтверждать каждую транзакцию, показывая текущий уровень вложенности транзакций (@@TRANCOUNT),
что вызвано особенностью работы MS SQL Server в режиме IMPLICIT_TRANSACTIONS ON: в этом режиме начало транзакции переводит @@ TRANCOUNT в значение 2, а не в 1.
Работа с MySQL, MS SQL Server и Oracle в примерах © EPAM Systems, RD Dep, 2016-2018 Стр: 473/545
Пример 44: взаимодействие конкурирующих транзакций
Грязное чтение в MS SQL Server может быть исследовано выполнением в двух отдельных сессиях следующих блоков кода:
MS SQL |
Решение 6.2.2.a (код для исследования аномалии грязного чтения) |
|
1 |
-- Транзакция A: |
|
|
-- Транзакция B: |
|
|||
2 |
PRINT CONCAT('Tr A ID = |
', @@SPID); |
PRINT CONCAT('Tr B ID = ', @@SPID); |
|||||
3 |
SET IMPLICIT_TRANSACTIONS ON; |
|
SET IMPLICIT_TRANSACTIONS ON; |
|||||
4 |
SET TRANSACTION ISOLATION LEVEL |
|
SET TRANSACTION ISOLATION LEVEL |
|||||
|
{УРОВЕНЬ}; |
|
|
|
{УРОВЕНЬ}; |
|
||
|
BEGIN TRANSACTION; |
|
|
BEGIN TRANSACTION; |
|
|||
|
PRINT CONCAT('Tr A START: ', |
|
PRINT CONCAT('Tr B START: ' , |
|||||
8 |
dbo.GET_CT() , ' in ', |
|
|
dbo.GET_CT(), ' in ', |
||||
|
dbo G |
|
|
|
|
dbo G |
|
|
10 |
|
|
|
|
|
PRINT CONCAT('Tr B SELECT-1: ', |
||
11 |
|
|
|
|
|
dbo.GET_CT()); |
|
|
12 |
WAITFOR DELAY '00:00:05'; |
|
SELECT [sb_is_active] |
|||||
13 |
|
|
|
|
|
FROM |
[subscriptions] |
|
14 |
|
|
|
|
|
WHERE |
[sb id] = 2; |
|
|
PRINT CONCAT('Tr A UPDATE: ', |
|
|
|
|
|||
16 |
dbo.GET_CT()); |
|
|
|
|
|
||
17 |
UPDATE [subscriptions] |
|
|
|
|
|
||
18 |
SET |
[sb_is_active] = |
|
|
|
|
|
|
19 |
CASE |
|
|
|
WAITFOR DELAY '00:00:10'; |
|||
20 |
WHEN |
[sb_is_active] = |
'Y' THEN |
'N' |
|
|
|
|
21 |
WHEN |
[sb_is_active] = |
'N' THEN |
'Y' |
|
|
|
|
22 |
END |
|
|
|
|
|
|
|
23 |
WHERE |
[sb id] = 2; |
|
|
|
|
||
24 |
|
|
|
|
|
PRINT CONCAT('Tr B SELECT-2: ', |
||
25 |
|
|
|
|
|
dbo.GET_CT()); |
|
|
26 |
|
|
|
|
|
SELECT [sb_is_active] |
||
27 |
|
|
|
|
|
FROM |
[subscriptions] |
|
28 |
WAITFOR DELAY '00:00:20'; |
|
WHERE |
[sb_id] = 2; |
|
|||
29 |
|
|
|
|
|
PRINT CONCAT('Tr B COMMIT: ', |
||
30 |
|
|
|
|
|
dbo.GET_CT()); |
|
|
31 |
|
|
|
|
|
COMMIT; |
|
|
32 |
|
|
|
|
|
PRINT CONCAT('TrC = |
', @@TRANCOUNT); |
|
33 |
|
|
|
|
|
COMMIT; |
|
|
34 |
|
|
|
|
|
PRINT CONCAT('TrC = |
', |
|
|
PRINT CONCAT('Tr A ROLLBACK: ', |
|
|
|
|
|||
36 |
dbo.GET_CT()); |
|
|
|
|
|
||
37 |
ROLLBACK; |
|
|
|
|
|
|
|
38 |
PRINT CONCAT('TrC = ', @@TRANCOUNT); |
|
|
|
Работа с MySQL, MS SQL Server и Oracle в примерах © EPAM Systems, RD Dep, 2016-2018 Стр: 474/545
Пример 44: взаимодействие конкурирующих транзакций
Итоговые результаты взаимодействия транзакций таковы.
|
|
|
Уровень изолированности транзакции B |
|
||
|
|
READ |
READ |
REPEATABLE |
SNAPSHOT |
SERIALIZABLE |
|
|
|
|
|||
|
|
UNCOMMITTED |
COMMITTED |
READ |
||
|
|
|
|
|||
|
|
|
Транзакция B |
Транзакция B |
|
Транзакция B оба |
|
|
|
оба раза читает |
|
||
|
|
Транзакция B |
оба раза читает |
Транзакция B |
раза читает |
|
|
|
успевает |
исходное |
исходное |
оба раза чи- |
исходное |
|
|
(корректное) |
||||
|
READ |
прочитать |
(корректное) |
тает исход- |
(корректное) |
|
|
значение, SE- |
|||||
|
UNCOMMITTED |
незафикси- |
значение, UP- |
ное (кор- |
значение, UP- |
|
|
LECT-2 в |
|||||
|
|
рованное |
DATE в тран- |
ректное) |
DATE в тран- |
|
|
|
транзакции B |
||||
|
|
значение |
закции A ждёт |
значение |
закции A ждёт |
|
|
|
ждёт завер- |
||||
|
|
|
завершения B |
|
завершения B |
|
|
|
|
шения A |
|
||
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Транзакция B |
Транзакция B |
|
Транзакция B оба |
|
|
|
оба раза читает |
|
||
|
|
Транзакция B |
оба раза читает |
Транзакция B |
раза читает |
|
|
|
успевает |
исходное |
исходное |
оба раза чи- |
исходное |
|
|
(корректное) |
||||
|
READ |
прочитать |
(корректное) |
тает исход- |
(корректное) |
|
|
значение, SE- |
|||||
|
COMMITTED |
незафикси- |
значение, UP- |
ное (кор- |
значение, UP- |
|
|
LECT-2 в |
|||||
|
|
рованное |
DATE в тран- |
ректное) |
DATE в тран- |
|
|
|
транзакции B |
||||
A |
|
значение |
закции A ждёт |
значение |
закции A ждёт |
|
|
|
|||||
транзакции |
|
|
ждёт завер- |
завершения B |
|
завершения B |
|
|
шения A |
|
|||
|
|
|
|
|||
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Транзакция B |
Транзакция B |
|
Транзакция B оба |
|
|
|
оба раза читает |
|
||
|
|
Транзакция B |
оба раза читает |
Транзакция B |
раза читает |
|
изолированности |
|
исходное |
||||
|
успевает |
исходное |
оба раза чи- |
исходное |
||
|
(корректное) |
|||||
|
|
|||||
|
REPEATABLE |
прочитать |
(корректное) |
тает исход- |
(корректное) |
|
|
значение, SE- |
|||||
|
READ |
незафикси- |
значение, UP- |
ное (кор- |
значение, UP- |
|
|
LECT-2 в |
|||||
|
|
рованное |
DATE в тран- |
ректное) |
DATE в тран- |
|
|
|
транзакции B |
||||
|
|
значение |
закции A ждёт |
значение |
закции A ждёт |
|
|
|
ждёт завер- |
||||
|
|
|
завершения B |
|
завершения B |
|
|
|
|
шения A |
|
||
Уровень |
|
|
|
|
|
|
|
|
Транзакция B |
Транзакция B |
|
Транзакция B оба |
|
|
|
|
|
|||
|
|
|
оба раза читает |
|
||
|
|
Транзакция B |
оба раза читает |
Транзакция B |
раза читает |
|
|
|
успевает |
исходное |
исходное |
оба раза чи- |
исходное |
|
|
(корректное) |
||||
|
|
прочитать |
(корректное) |
тает исход- |
(корректное) |
|
|
SNAPSHOT |
значение, SE- |
||||
|
незафикси- |
значение, UP- |
ное (кор- |
значение, UP- |
||
|
|
LECT-2 в |
||||
|
|
рованное |
DATE в тран- |
ректное) |
DATE в тран- |
|
|
|
транзакции B |
||||
|
|
значение |
закции A ждёт |
значение |
закции A ждёт |
|
|
|
ждёт завер- |
||||
|
|
|
завершения B |
|
завершения B |
|
|
|
|
шения A |
|
||
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Транзакция B |
Транзакция B |
|
Транзакция B оба |
|
|
|
оба раза читает |
|
||
|
|
Транзакция B |
оба раза читает |
Транзакция B |
раза читает |
|
|
|
успевает |
исходное |
исходное |
оба раза чи- |
исходное |
|
|
(корректное) |
||||
|
|
прочитать |
(корректное) |
тает исход- |
(корректное) |
|
|
SERIALIZABLE |
значение, SE- |
||||
|
незафикси- |
значение, UP- |
ное (кор- |
значение, UP- |
||
|
|
LECT-2 в |
||||
|
|
рованное |
DATE в тран- |
ректное) |
DATE в тран- |
|
|
|
транзакции B |
||||
|
|
значение |
закции A ждёт |
значение |
закции A ждёт |
|
|
|
ждёт завер- |
||||
|
|
|
завершения B |
|
завершения B |
|
|
|
|
шения A |
|
||
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Работа с MySQL, MS SQL Server и Oracle в примерах © EPAM Systems, RD Dep, 2016-2018 Стр: 475/545
Пример 44: взаимодействие конкурирующих транзакций
Потерянное обновление MS SQL Server может быть исследовано выполнением в двух отдельных сессиях следующих блоков кода:
MS SQL I Решение 6.2.2.a (код для исследования аномалии потерянного обновления) |
1 |
-- Транзакция A: |
-- Транзакция B: |
||
2 |
PRINT CONCAT('Tr A ID = ', @@SPID); |
PRINT CONCAT('Tr B ID = ', @@SPID); |
||
3 |
SET IMPLICIT TRANSACTIONS ON; |
SET IMPLICIT TRANSACTIONS ON; |
||
4 |
SET TRANSACTION ISOLATION |
SET TRANSACTION ISOLATION |
||
5 |
LEVEL {УРОВЕНЬ}; |
LEVEL {УРОВЕНЬ}; |
||
|
|
|
|
|
6 |
BEGIN TRANSACTION; |
BEGIN TRANSACTION; |
||
7 |
PRINT CONCAT('Tr A START: ', |
PRINT CONCAT('Tr B START: ', |
||
8 |
dbo GET CT(), ' in ', |
dbo.GET CT(), ' in ', |
||
9 |
dbo G |
|
dbo G |
|
|
|
|
|
|
10 |
PRINT CONCAT('Tr A SELECT: ', |
|
|
|
11 |
dbo GET CT () ) ; |
|
|
|
12 |
SELECT [sb is active] |
WAITFOR DELAY '00:00:05'; |
||
13 |
FROM |
[subscriptions] |
|
|
14 |
WHERE |
[sb id] = 2; |
|
|
15 |
|
|
PRINT CONCAT('Tr B SELECT: ', |
|
16 |
|
|
dbo GET CT )); |
|
17 |
WAITFOR DELAY '00:00:10'; |
SELECT [sb is active] |
||
18 |
|
|
FROM |
[subscriptions] |
19 |
|
|
WHERE |
[sb id] = 2; |
20 |
PRINT CONCAT('Tr A UPDATE: ', |
|
|
|
21 |
dbo GET CT () ) ; |
|
|
|
22 |
UPDATE [subscriptions] |
|
|
|
23 |
SET |
[sb is active] = 'Y' |
WAITFOR DELAY '00:00:10'; |
|
24 |
WHERE |
[sb id] = 2; |
|
|
25 |
PRINT CONCAT('Tr A COMMIT: ', |
|
|
|
26 |
dbo GET CT () ) ; |
|
|
|
|
|
|
|
|
27 |
COMMIT; |
|
|
|
28 |
PRINT CONCAT('TrC = ', @@TRANCOUNT); |
|
|
|
29 |
COMMIT; |
|
|
|
30 |
PRINT CONCAT('TrC = ', |
|
|
|
|
|
|
|
|
31 |
|
|
PRINT CONCAT('Tr B UPDATE: ', |
|
32 |
|
|
dbo.GET CT () ) ; |
|
33 |
|
|
UPDATE [subscriptions] |
|
34 |
WAITFOR DELAY '00:00:10'; |
SET |
[sb is active] = 'N' |
|
35 |
|
|
WHERE |
[sb id] = 2; |
36 |
|
|
PRINT CONCAT('Tr B COMMIT: ', |
|
37 |
|
|
dbo GET CT )); |
|
38 |
|
|
COMMIT; |
|
39 |
|
|
PRINT CONCAT('TrC = ', @@TRANCOUNT); |
|
40 |
|
|
COMMIT; |
|
41 |
|
|
PRINT CONCAT('TrC = ', |
|
|
|
|
||
42 |
PRINT CONCAT('Tr A SELECT AFTER: ', |
PRINT CONCAT('Tr B SELECT AFTER: ', |
||
43 |
dbo GET CT () ) ; |
dbo.GET CT () ) ; |
||
44 |
SELECT [sb is active] |
SELECT [sb is active] |
||
45 |
FROM |
[subscriptions] |
FROM |
[subscriptions] |
46 |
WHERE |
[sb id] = 2 ■ |
WHERE |
[sb id] = 2; |
Работа с MySQL, MS SQL Server и Oracle в примерах © EPAM Systems, RD Dep, 2016-2018 Стр: 476/545
Пример 44: взаимодействие конкурирующих транзакций
Итоговые результаты взаимодействия транзакций таковы.
|
|
|
Уровень изолированности транзакции B |
|
||
|
|
READ |
READ |
REPEATABLE |
SNAPSHOT |
SERIALIZABLE |
|
|
|
||||
|
|
UNCOMMITTED |
COMMITTED |
READ |
||
|
|
|
|
|||
|
|
|
|
|
Обновление |
|
|
|
|
|
Обновление |
транзакции A |
Обновление |
|
|
|
|
сохранено, |
||
|
|
|
|
транзакции A |
транзакции A |
|
|
|
|
|
транзакция B |
||
|
|
Обновление |
Обновление |
сохранено, |
сохранено, |
|
|
READ |
отменена (по- |
||||
|
транзакции A |
транзакции A |
UPDATE в |
UPDATE в |
||
|
UNCOMMITTED |
пытка обновить |
||||
|
утеряно |
утеряно |
транзакции A |
транзакции A |
||
|
|
заблоки- |
||||
|
|
|
|
ждёт заверше- |
ждёт заверше- |
|
|
|
|
|
рованную запись |
||
|
|
|
|
ния B |
в режиме |
ния B |
|
|
|
|
|
|
|
|
|
|
|
|
SNAPSHOT) |
|
|
|
|
|
|
|
|
|
|
|
|
|
Обновление |
|
|
|
|
|
Обновление |
транзакции A |
Обновление |
|
|
|
|
сохранено, |
||
|
|
|
|
транзакции A |
транзакции A |
|
|
|
|
|
транзакция B |
||
|
|
Обновление |
Обновление |
сохранено, |
сохранено, |
|
|
READ |
отменена (по- |
||||
|
транзакции A |
транзакции A |
UPDATE в |
UPDATE в |
||
|
COMMITTED |
пытка обновить |
||||
|
утеряно |
утеряно |
транзакции A |
транзакции A |
||
|
|
заблоки- |
||||
|
|
|
|
ждёт заверше- |
ждёт заверше- |
|
|
|
|
|
рованную запись |
||
A |
|
|
|
ния B |
в режиме |
ния B |
|
|
|
|
|
||
транзакции |
|
|
|
|
|
|
|
|
|
|
SNAPSHOT) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Обновление |
|
|
|
|
|
|
транзакции A |
|
изолированности |
|
|
|
|
сохранено, |
|
|
|
|
|
в режиме |
|
|
|
|
Обновление |
Обновление |
Взаимная бло- |
транзакция B |
Взаимная бло- |
|
REPEATABLE |
транзакции A |
транзакции A |
кировка тран- |
отменена (по- |
кировка тран- |
|
READ |
утеряно |
утеряно |
закций |
пытка обновить |
закций |
|
|
заблоки- |
||||
|
|
|
|
|
|
|
|
|
|
|
|
рованную запись |
|
Уровень |
|
|
|
|
SNAPSHOT) |
|
|
|
|
|
транзакции A |
|
|
|
|
|
|
|
Обновление |
|
|
|
|
|
Транзакция A |
сохранено, |
Транзакция A |
|
|
|
|
отменена (по- |
отменена (по- |
|
|
|
|
|
транзакция B |
||
|
|
Обновление |
Обновление |
пытка обновить |
пытка обновить |
|
|
|
отменена (по- |
||||
|
SNAPSHOT |
транзакции A |
транзакции A |
заблоки- |
заблоки- |
|
|
пытка обновить |
|||||
|
|
утеряно |
утеряно |
рованную запись |
рованную запись |
|
|
|
|
|
в режиме |
заблоки- |
в режиме |
|
|
|
|
рованную запись |
||
|
|
|
|
SNAPSHOT) |
SNAPSHOT) |
|
|
|
|
|
в режиме |
||
|
|
|
|
|
|
|
|
|
|
|
|
SNAPSHOT) |
|
|
|
|
|
|
|
|
|
|
|
|
|
Обновление |
|
|
|
Обновление |
Обновление |
|
транзакции A |
|
|
|
|
сохранено, |
|
||
|
|
транзакции A |
транзакции A |
|
|
|
|
|
|
транзакция B |
|
||
|
|
утеряно, |
утеряно, |
Взаимная бло- |
Взаимная бло- |
|
|
|
отменена (по- |
||||
|
SERIALIZABLE |
COMMIT в |
COMMIT в |
кировка тран- |
кировка тран- |
|
|
пытка обновить |
|||||
|
|
транзакции A |
транзакции A |
закций |
закций |
|
|
|
заблоки- |
||||
|
|
ждёт заверше- |
ждёт заверше- |
|
|
|
|
|
|
рованную запись |
|
||
|
|
ния B |
ния B |
|
|
|
|
|
|
в режиме |
|
||
|
|
|
|
|
|
|
|
|
|
|
|
SNAPSHOT) |
|
|
|
|
|
|
|
|
В учебных целях рассмотрим, что было бы, если бы в коде обеих транзакций мы «забыли» дописать второй COMMIT (см. подобранности в решении{408} задачи
6.1.1. a<408}).
Работа с MySQL, MS SQL Server и Oracle в примерах © EPAM Systems, RD Dep, 2016-2018 Стр: 477/545
Пример 44: взаимодействие конкурирующих транзакций
Итоговые ошибочные результаты взаимодействия транзакций приняли бы следующий вид.
|
|
|
Уровень изолированности транзакции B |
|
|||
|
|
READ |
READ |
REPEATABLE |
SNAPSHOT |
SERIALIZABLE |
|
|
|
UNCOMMITTED |
COMMITTED |
READ |
|||
|
|
|
|
||||
|
|
|
|
|
|
|
|
|
|
Обновление |
Обновление |
Обновление |
Обновление |
|
|
|
|
транзакции A |
транзакции A |
транзакции A |
транзакции A |
|
|
|
READ |
утеряно, UP- |
утеряно, UP- |
утеряно, UP- |
утеряно, UP- |
Обновление |
|
|
DATE в тран- |
DATE в тран- |
DATE в тран- |
DATE в тран- |
транзакции A |
||
|
UNCOMMITTED |
||||||
|
закции B ждёт |
закции B ждёт |
закции B ждёт |
закции B ждёт |
утеряно |
||
|
|
||||||
|
|
завершения |
завершения |
завершения |
завершения |
|
|
|
|
сессии A |
сессии A |
сессии A |
сессии A |
|
|
|
|
|
|
|
|
|
|
|
|
Обновление |
Обновление |
Обновление |
Обновление |
|
|
|
|
транзакции A |
транзакции A |
транзакции A |
транзакции A |
|
|
|
READ |
утеряно, UP- |
утеряно, UP- |
утеряно, UP- |
утеряно, UP- |
Обновление |
|
|
DATE в тран- |
DATE в тран- |
DATE в тран- |
DATE в тран- |
транзакции A |
||
A |
COMMITTED |
||||||
|
|
|
|
|
|||
транзакции |
закции B ждёт |
закции B ждёт |
закции B ждёт |
закции B ждёт |
утеряно |
||
|
|||||||
|
завершения |
завершения |
завершения |
завершения |
|
||
|
|
|
|||||
|
|
сессии A |
сессии A |
сессии A |
сессии A |
|
|
|
|
|
|
|
|
|
|
|
|
Обновление |
Обновление |
Обновление |
Обновление |
|
|
изолированности |
|
транзакции A |
транзакции A |
транзакции A |
транзакции A |
|
|
REPEATABLE |
утеряно, UP- |
утеряно, UP- |
утеряно, UP- |
утеряно, UP- |
Взаимная бло- |
||
|
|||||||
|
DATE в тран- |
DATE в тран- |
DATE в тран- |
DATE в тран- |
кировка тран- |
||
|
READ |
||||||
|
закции B ждёт |
закции B ждёт |
закции B ждёт |
закции B ждёт |
закций |
||
|
|
||||||
|
|
завершения |
завершения |
завершения |
завершения |
|
|
|
|
сессии A |
сессии A |
сессии A |
сессии A |
|
|
|
|
|
|
|
|
|
|
Уровень |
|
Обновление |
Обновление |
|
Обновление |
|
|
|
транзакции A |
транзакции A |
|
транзакции A |
|
||
|
|
|
|
||||
|
|
утеряно, UP- |
утеряно, UP- |
Обновление |
утеряно, UP- |
Обновление |
|
|
SNAPSHOT |
DATE в тран- |
DATE в тран- |
транзакции A |
DATE в тран- |
транзакции A |
|
|
|
закции B ждёт |
закции B ждёт |
утеряно |
закции B ждёт |
утеряно |
|
|
|
завершения |
завершения |
|
завершения |
|
|
|
|
сессии A |
сессии A |
|
сессии A |
|
|
|
|
Обновление |
Обновление |
|
Обновление |
|
|
|
|
транзакции A |
транзакции A |
|
транзакции A |
|
|
|
|
утеряно, UP- |
утеряно, UP- |
Взаимная бло- |
утеряно, UP- |
Взаимная бло- |
|
|
SERIALIZABLE |
DATE в тран- |
DATE в тран- |
кировка тран- |
DATE в тран- |
кировка тран- |
|
|
|
закции B ждёт |
закции B ждёт |
закций |
закции B ждёт |
закций |
|
|
|
завершения |
завершения |
|
завершения |
|
|
|
|
сессии A |
сессии A |
|
сессии A |
|
|
|
|
|
|
|
|
|
Обратите внимание на формулировку «UPDATE в транзакции B ждёт завершения сессии А». Здесь имеется в виду именно вся сессия взаимодействия с СУБД, а не просто транзакция. Из-за «забытого» COMMIT обе транзакции фактически завершаются именно в момент закрытия сессии с СУБД.
Чтобы получить ещё один вариант поведения СУБД, необходимо явно блокировать читаемые записи (UPDLOCK) в первой операции (чтении). В данном случае
это не было сделано, чтобы продемонстрировать наиболее типичное поведение MS SQL Server. Проверить же остальные случаи реакции СУБД вам предлагается самостоятельно в задании 6.2.2.TSK.E{464}.
Работа с MySQL, MS SQL Server и Oracle в примерах © EPAM Systems, RD Dep, 2016-2018 Стр: 478/545
Пример 44: взаимодействие конкурирующих транзакций
Неповторяющееся чтение в MS SQL Server может быть исследовано вы-
полнением в двух отдельных сессиях следующих блоков кода:
MS SQL I Решение 6.2.2.a (код для исследования аномалии неповторяющегося чтения) |
1 |
-- Транзакция A: |
|
|
-- Транзакция B: |
|
||
2 |
PRINT CONCAT('Tr A ID = |
', @@SPID); |
PRINT CONCAT('Tr B ID = ', @@SPID); |
||||
3 |
SET IMPLICIT_TRANSACTIONS ON; |
|
SET IMPLICIT_TRANSACTIONS ON; |
||||
4 |
SET TRANSACTION ISOLATION LEVEL |
|
SET TRANSACTION ISOLATION LEVEL |
||||
|
{УРОВЕНЬ}; |
|
|
{УРОВЕНЬ}; |
|
||
|
BEGIN TRANSACTION; |
|
|
BEGIN TRANSACTION; |
|
||
|
PRINT CONCAT('Tr A START: ', |
|
PRINT CONCAT('Tr B START: ', |
||||
8 |
dbo.GET_CT() , ' in ', |
|
|
dbo.GET_CT(), ' in ', |
|||
|
dbo G |
|
|
|
dbo G |
|
|
10 |
|
|
|
|
PRINT CONCAT('Tr B SELECT-1: ', |
||
11 |
|
|
|
|
dbo.GET_CT()); |
|
|
12 |
WAITFOR DELAY '00:00:05'; |
|
SELECT [sb_is_active] |
||||
13 |
|
|
|
|
FROM |
[subscriptions] |
|
14 |
|
|
|
|
WHERE |
[sb id] = 2; |
|
|
PRINT CONCAT('Tr A UPDATE: ', |
|
|
|
|
||
16 |
dbo.GET_CT()); |
|
|
|
|
|
|
17 |
UPDATE [subscriptions] |
|
|
|
|
|
|
18 |
SET |
[sb_is_active] = |
|
|
|
|
|
19 |
CASE |
|
|
|
|
|
|
20 |
WHEN |
[sb_is_active] = |
'Y' THEN |
'N' |
|
|
|
21 |
WHEN |
[sb_is_active] = |
'N' THEN |
'Y' |
|
|
|
22 |
END |
|
|
|
WAITFOR DELAY '00:00:10'; |
||
23 |
WHERE [sb_id] = 2; |
|
|
|
|
|
|
24 |
PRINT CONCAT('Tr A COMMIT: ', |
|
|
|
|
||
25 |
dbo.GET_CT() ); |
|
|
|
|
|
|
26 |
COMMIT; |
|
|
|
|
|
|
27 |
PRINT CONCAT('TrC = ', @@TRANCOUNT); |
|
|
|
|||
28 |
COMMIT; |
|
|
|
|
|
|
|
PRINT CONCAT('TrC = ', @@TRANCOUNT), |
|
|
|
|||
30 |
|
|
|
|
PRINT CONCAT('Tr B SELECT-2: ', |
||
31 |
|
|
|
|
dbo.GET_CT()); |
|
|
32 |
|
|
|
|
SELECT [sb_is_active] |
||
33 |
|
|
|
|
FROM |
[subscriptions] |
|
34 |
|
|
|
|
WHERE |
[sb_id] = 2; |
|
35 |
|
|
|
|
PRINT CONCAT('Tr B COMMIT: ', |
||
36 |
|
|
|
|
dbo.GET_CT()); |
|
|
37 |
|
|
|
|
COMMIT; |
|
|
38 |
|
|
|
|
PRINT CONCAT('TrC = |
', @@TRANCOUNT); |
|
39 |
|
|
|
|
COMMIT; |
|
|
40 |
|
|
|
|
PRINT CONCAT('TrC = |
', @@TRANCOUNT); |
|
|
|
|
|
|
|
|
|
Работа с MySQL, MS SQL Server и Oracle в примерах © EPAM Systems, RD Dep, 2016-2018 Стр: 479/545