Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Скачиваний:
9
Добавлен:
15.01.2021
Размер:
14.96 Mб
Скачать

Пример 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