
Бази даних-20210115T104840Z-001 / Реферат на тему _Современные СУБД_ / Using_MySql,_MS_SQL_Server_and_Oracle(1)
.pdf
Пример 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 |
|
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.GET_ISOLATION_LEVEL()); |
|
dbo.GET_ISOLATION_LEVEL()); |
|
||
|
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; |
|
|
15 |
|
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' |
|
WAITFOR DELAY '00:00:10'; |
|
21WHEN [sb_is_active] = 'N' THEN 'Y'
22END
23WHERE [sb_id] = 2;
24PRINT CONCAT('Tr A COMMIT: ',
25dbo.GET_CT());
26COMMIT;
27PRINT CONCAT('TrC = ', @@TRANCOUNT);
28COMMIT;
29PRINT 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 Стр: 450/545

Пример 44: взаимодействие конкурирующих транзакций
Итоговые результаты взаимодействия транзакций таковы.
|
|
|
Уровень изолированности транзакции B |
|
|||
|
|
READ |
READ |
REPEATABLE |
SNAPSHOT |
SERIALIZABLE |
|
|
|
UNCOMMITTED |
COMMITTED |
READ |
|||
|
|
|
|
||||
|
|
|
|
Первый и вто- |
|
Первый и вто- |
|
|
|
Первый и вто- |
Первый и вто- |
рой SELECT |
Первый и вто- |
рой SELECT |
|
|
READ |
рой SELECT |
рой SELECT |
возвратили |
рой SELECT |
возвратили |
|
|
возвратили |
возвратили |
одинаковые |
возвратили |
одинаковые |
||
|
UNCOMMITTED |
||||||
|
разные дан- |
разные дан- |
данные, тран- |
одинаковые |
данные, тран- |
||
|
|
||||||
|
|
ные |
ные |
закция A ждёт |
данные |
закция A ждёт |
|
|
|
|
|
завершения B |
|
завершения B |
|
|
|
|
|
Первый и вто- |
|
Первый и вто- |
|
|
|
Первый и вто- |
Первый и вто- |
рой SELECT |
Первый и вто- |
рой SELECT |
|
|
READ |
рой SELECT |
рой SELECT |
возвратили |
рой SELECT |
возвратили |
|
A |
возвратили |
возвратили |
одинаковые |
возвратили |
одинаковые |
||
COMMITTED |
|||||||
транзакции |
разные дан- |
разные дан- |
данные, тран- |
одинаковые |
данные, тран- |
||
|
|||||||
|
ные |
ные |
закция A ждёт |
данные |
закция A ждёт |
||
|
|
||||||
|
|
|
|
завершения B |
|
завершения B |
|
|
|
|
|
Первый и вто- |
|
Первый и вто- |
|
изолированности |
|
Первый и вто- |
Первый и вто- |
рой SELECT |
Первый и вто- |
рой SELECT |
|
REPEATABLE |
рой SELECT |
рой SELECT |
возвратили |
рой SELECT |
возвратили |
||
|
|||||||
|
возвратили |
возвратили |
одинаковые |
возвратили |
одинаковые |
||
|
READ |
||||||
|
разные дан- |
разные дан- |
данные, тран- |
одинаковые |
данные, тран- |
||
|
|
||||||
|
|
ные |
ные |
закция A ждёт |
данные |
закция A ждёт |
|
|
|
|
|
завершения B |
|
завершения B |
|
Уровень |
|
|
|
Первый и вто- |
|
Первый и вто- |
|
|
Первый и вто- |
Первый и вто- |
рой SELECT |
Первый и вто- |
рой SELECT |
||
|
|
||||||
|
|
рой SELECT |
рой SELECT |
возвратили |
рой SELECT |
возвратили |
|
|
SNAPSHOT |
возвратили |
возвратили |
одинаковые |
возвратили |
одинаковые |
|
|
|
разные дан- |
разные дан- |
данные, тран- |
одинаковые |
данные, тран- |
|
|
|
ные |
ные |
закция A ждёт |
данные |
закция A ждёт |
|
|
|
|
|
завершения B |
|
завершения B |
|
|
|
|
|
Первый и вто- |
|
Первый и вто- |
|
|
|
Первый и вто- |
Первый и вто- |
рой SELECT |
Первый и вто- |
рой SELECT |
|
|
|
рой SELECT |
рой SELECT |
возвратили |
рой SELECT |
возвратили |
|
|
SERIALIZABLE |
возвратили |
возвратили |
одинаковые |
возвратили |
одинаковые |
|
|
|
разные дан- |
разные дан- |
данные, тран- |
одинаковые |
данные, тран- |
|
|
|
ные |
ные |
закция A ждёт |
данные |
закция A ждёт |
|
|
|
|
|
завершения B |
|
завершения B |
Чтобы получить ещё один вариант поведения СУБД, необходимо явно блокировать читаемые записи (UPDLOCK) в первой операции чтения. В данном случае это не было сделано, чтобы продемонстрировать наиболее типичное поведение MS SQL Server. Проверить же остальные случаи реакции СУБД вам предлагается самостоятельно в задании 6.2.2.TSK.E{464}.
Работа с MySQL, MS SQL Server и Oracle в примерах © EPAM Systems, RD Dep, 2016–2018 Стр: 451/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 |
|
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.GET_ISOLATION_LEVEL()); |
|
dbo.GET_ISOLATION_LEVEL()); |
|
||
|
10 |
|
|
|
|
PRINT CONCAT('Tr B COUNT-1: ', |
|
|
|
11 |
|
|
|
|
dbo.GET_CT()); |
|
|
|
12 |
|
WAITFOR DELAY '00:00:05'; |
|
SELECT |
COUNT(*) |
|
|
|
13 |
|
|
|
|
FROM |
[subscriptions] |
|
|
14 |
|
|
|
|
WHERE |
[sb_id] > 500; |
|
|
15 |
|
PRINT CONCAT('Tr A INSERT: ', |
|
|
|
|
|
|
16 |
|
dbo.GET_CT()); |
|
|
|
|
|
|
17 |
|
|
|
|
|
|
|
|
18 |
|
SET IDENTITY_INSERT |
|
|
|
|
|
|
19 |
|
[subscriptions] ON; |
|
|
|
|
|
|
20 |
|
|
|
|
|
|
|
|
21 |
|
INSERT INTO [subscriptions] |
|
|
|
|
|
|
22 |
|
|
([sb_id], |
|
|
|
|
|
23 |
|
|
[sb_subscriber], |
|
|
|
|
|
24 |
|
|
[sb_book], |
|
WAITFOR DELAY '00:00:10'; |
|
|
|
25 |
|
|
[sb_start], |
|
|
|
|
|
26 |
|
|
[sb_finish], |
|
|
|
|
|
27 |
|
|
[sb_is_active]) |
|
|
|
|
|
28 |
|
|
VALUES (1000, |
|
|
|
|
|
29 |
|
|
1, |
|
|
|
|
|
30 |
|
|
1, |
|
|
|
|
|
31 |
|
|
'2025-01-12', |
|
|
|
|
|
32 |
|
|
'2026-02-12', |
|
|
|
|
|
33 |
|
|
'N'); |
|
|
|
|
34 |
|
|
|
|
|
|
|
35SET IDENTITY_INSERT
36[subscriptions] OFF;
37 |
|
PRINT CONCAT('Tr B COUNT-2: ', |
|
38 |
|
dbo.GET_CT()); |
|
39 |
WAITFOR DELAY '00:00:10'; |
|
|
40 |
|
SELECT |
COUNT(*) |
41 |
|
FROM |
[subscriptions] |
42 |
|
WHERE |
[sb_id] > 500; |
43 |
PRINT CONCAT('Tr A ROLLBACK: ', |
|
|
44 |
dbo.GET_CT()); |
WAITFOR DELAY '00:00:15'; |
|
45 |
ROLLBACK; |
|
|
46 |
PRINT CONCAT('TrC = ', @@TRANCOUNT); |
|
|
47 |
|
PRINT CONCAT('Tr B COUNT-3: ', |
|
48 |
|
dbo.GET_CT()); |
|
49 |
|
SELECT |
COUNT(*) |
50 |
|
FROM |
[subscriptions] |
51 |
|
WHERE |
[sb_id] > 500; |
52 |
|
PRINT CONCAT('Tr B COMMIT: ', |
|
53 |
|
dbo.GET_CT()); |
|
54 |
|
COMMIT; |
|
55 |
|
PRINT CONCAT('TrC = ', @@TRANCOUNT); |
|
56 |
|
COMMIT; |
|
57 |
|
PRINT CONCAT('TrC = ', @@TRANCOUNT); |
Работа с MySQL, MS SQL Server и Oracle в примерах © EPAM Systems, RD Dep, 2016–2018 Стр: 452/545

Пример 44: взаимодействие конкурирующих транзакций
Итоговые результаты взаимодействия транзакций таковы.
|
|
|
Уровень изолированности транзакции B |
|
|||
|
|
READ |
READ |
REPEATABLE |
SNAPSHOT |
SERIALIZABLE |
|
|
|
UNCOMMITTED |
COMMITTED |
READ |
|||
|
|
|
|
||||
|
|
|
Транзакция B |
Транзакция B |
Транзакция |
Транзакция B не |
|
|
|
Транзакция B |
не получает до- |
не получает до- |
получает до- |
||
|
|
B не полу- |
|||||
|
|
успевает обра- |
ступа к «фан- |
ступа к «фан- |
ступа к «фан- |
||
|
READ |
чает до- |
|||||
|
ботать «фан- |
томной за- |
томной за- |
томной записи», |
|||
|
UNCOMMITTED |
ступа к |
|||||
|
томную за- |
писи», её |
писи», её |
INSERT в тран- |
|||
|
|
«фантомной |
|||||
|
|
пись» |
COUNT-2 ждёт |
COUNT-2 ждёт |
закции A ждёт |
||
|
|
записи» |
|||||
|
|
|
завершения A |
завершения A |
завершения B |
||
|
|
|
|
||||
|
|
|
Транзакция B |
Транзакция B |
Транзакция |
Транзакция B не |
|
|
|
Транзакция B |
не получает до- |
не получает до- |
получает до- |
||
|
|
B не полу- |
|||||
|
|
успевает обра- |
ступа к «фан- |
ступа к «фан- |
ступа к «фан- |
||
|
READ |
чает до- |
|||||
|
ботать «фан- |
томной за- |
томной за- |
томной записи», |
|||
A |
COMMITTED |
ступа к |
|||||
томную за- |
писи», её |
писи», её |
INSERT в тран- |
||||
транзакции |
|
«фантомной |
|||||
|
пись» |
COUNT-2 ждёт |
COUNT-2 ждёт |
закции A ждёт |
|||
|
записи» |
||||||
|
|
||||||
|
|
|
завершения A |
завершения A |
завершения B |
||
|
|
|
|
||||
|
|
Транзакция B |
Транзакция B |
Транзакция B |
|
Транзакция B не |
|
|
|
успевает обра- |
Транзакция |
||||
изолированности |
|
не получает до- |
не получает до- |
получает до- |
|||
|
ния B |
B не полу- |
|||||
|
|
|
|
||||
|
|
ботать «фан- |
ступа к «фан- |
ступа к «фан- |
ступа к «фан- |
||
|
REPEATABLE |
томную за- |
чает до- |
||||
|
томной за- |
томной за- |
томной записи», |
||||
|
READ |
пись», INSERT |
ступа к |
||||
|
писи», её |
писи», её |
INSERT в тран- |
||||
|
|
в транзакции A |
«фантомной |
||||
|
|
COUNT-2 ждёт |
COUNT-2 ждёт |
закции A ждёт |
|||
|
|
ждёт заверше- |
записи» |
||||
|
|
завершения A |
завершения A |
завершения B |
|||
|
|
|
|
||||
Уровень |
|
|
|
|
|
|
|
|
успевает обра- |
ступа к «фан- |
ступа к «фан- |
|
ступа к «фан- |
||
|
|
|
Транзакция B |
Транзакция B |
Транзакция |
Транзакция B не |
|
|
|
Транзакция B |
не получает до- |
не получает до- |
получает до- |
||
|
|
B не полу- |
|||||
|
|
|
|
|
|
||
|
SNAPSHOT |
ботать «фан- |
томной за- |
томной за- |
чает до- |
томной записи», |
|
|
ступа к |
||||||
|
|
томную за- |
писи», её |
писи», её |
INSERT в тран- |
||
|
|
«фантомной |
|||||
|
|
пись» |
COUNT-2 ждёт |
COUNT-2 ждёт |
закции A ждёт |
||
|
|
записи» |
|||||
|
|
|
завершения A |
завершения A |
завершения B |
||
|
|
|
|
||||
|
|
|
Транзакция B |
Транзакция B |
Транзакция |
Транзакция B не |
|
|
|
Транзакция B |
не получает до- |
не получает до- |
получает до- |
||
|
|
B не полу- |
|||||
|
|
успевает обра- |
ступа к «фан- |
ступа к «фан- |
ступа к «фан- |
||
|
|
чает до- |
|||||
|
SERIALIZABLE |
ботать «фан- |
томной за- |
томной за- |
томной записи», |
||
|
ступа к |
||||||
|
|
томную за- |
писи», её |
писи», её |
INSERT в тран- |
||
|
|
«фантомной |
|||||
|
|
пись» |
COUNT-2 ждёт |
COUNT-2 ждёт |
закции A ждёт |
||
|
|
записи» |
|||||
|
|
|
завершения A |
завершения A |
завершения B |
||
|
|
|
|
На этом решение для MS SQL Server завершено.
Переходим к Oracle. Данная СУБД поддерживает два уровня изолированности транзакций и два режима транзакций, комбинации которых мы и рассмотрим:
•Уровни изолированности:
oREAD COMMITTED;
oSERIALIZABLE.
•Режимы:
oREAD ONLY (фактически, это — тоже уровень изолированности, экви-
валентный REPEATABLE READ и/или SERIALIZABLE в других СУБД); o READ WRITE.
Для выполнения эксперимента используем командный файл:
start cmd.exe /c "echo exit | sqlplus ПОЛЬЗОВАТЕЛЬ/ПАРОЛЬ@КОМПЬЮТЕР @a.sql & pause"
start cmd.exe /c "echo exit | sqlplus ПОЛЬЗОВАТЕЛЬ/ПАРОЛЬ@КОМПЬЮТЕР @b.sql & pause"
Работа с MySQL, MS SQL Server и Oracle в примерах © EPAM Systems, RD Dep, 2016–2018 Стр: 453/545

Пример 44: взаимодействие конкурирующих транзакций
Для упрощения кода приведённых далее запросов создадим функции
GET_IDS_AND_ISOLATION_LEVEL и GET_CT, возвращающие, соответственно, зна-
чение параметров транзакции и значение текущего времени.
Oracle |
Решение 6.2.2.a (код и запрос для проверки работоспособности сервисных функций) |
1CREATE FUNCTION GET_IDS_AND_ISOLATION_LEVEL
2RETURN NVARCHAR2
3IS
4session_id NUMBER(10);
5session_sn NUMBER(10);
6session_isolation_level NVARCHAR2(150);
7trans_id VARCHAR(100);
8BEGIN
9trans_id := DBMS_TRANSACTION.LOCAL_TRANSACTION_ID(FALSE);
10SELECT "session".sid AS "session_id",
11"session".serial# AS "session_sn",
12CASE BITAND("transaction".flag, POWER(2, 28))
13WHEN 0 THEN 'READ COMMITTED'
14ELSE 'SERIALIZABLE'
15END AS "session_isolation_level"
16 INTO session_id,
17session_sn,
18session_isolation_level
19 |
FROM v$transaction "transaction" |
20JOIN v$session "session"
21ON "transaction".addr = "session".taddr
22 |
|
AND "session".sid = SYS_CONTEXT('USERENV', 'SID'); |
23 |
|
|
|
|
|
24RETURN 'ID = ' || session_id || ', SN = ' || session_sn || ', in ' ||
25session_isolation_level;
26END;
27
28CREATE FUNCTION GET_CT
29RETURN NVARCHAR2
30IS
31BEGIN
32RETURN TO_CHAR(SYSTIMESTAMP,'HH24:MI:SS.FF');
33END;
34
35 SELECT GET_CT FROM DUAL;
26SELECT GET_IDS_AND_ISOLATION_LEVEL FROM DUAL;
Ксожалению, в Oracle 11gR2 не существует документированного способа различить READ ONLY и READ WRITE транзакции, равно как не существует и спо-
соба комбинировать эти параметры с указанием уровня изолированности. И если вторую проблему можно обойти отдельной настройкой параметров сессии и транзакции, с первой проблемой (пока?) ничего нельзя поделать.
Поскольку Oracle (как и MySQL) не поддерживает вложенные транзакции, здесь (в отличие от MS SQL Server) мы не будем следить за текущим уровнем транзакций.
Работа с MySQL, MS SQL Server и Oracle в примерах © EPAM Systems, RD Dep, 2016–2018 Стр: 454/545

Пример 44: взаимодействие конкурирующих транзакций
Грязное чтение в Oracle не существует, но проверить это можно выполнением в двух отдельных сессиях следующих блоков кода:
|
Oracle |
|
Решение 6.2.2.a (код для исследования аномалии грязного чтения) |
||||||
|
1 |
|
-- Транзакция A: |
|
-- Транзакция B: |
|
|||
|
2 |
|
ALTER SESSION SET |
|
ALTER SESSION SET |
|
|||
|
3 |
|
ISOLATION_LEVEL = {УРОВЕНЬ}; |
|
ISOLATION_LEVEL = {УРОВЕНЬ}; |
|
|||
|
4 |
|
SET TRANSACTION {РЕЖИМ}; |
|
SET TRANSACTION {РЕЖИМ}; |
|
|||
|
5 |
|
SELECT 'Tr A: ' || |
|
SELECT |
'Tr B: ' || |
|
||
|
6 |
|
GET_IDS_AND_ISOLATION_LEVEL |
|
GET_IDS_AND_ISOLATION_LEVEL |
|
|||
|
7 |
|
FROM DUAL; |
|
FROM DUAL; |
|
|||
|
8 |
|
SELECT 'Tr A START: ' || |
|
SELECT |
'Tr B START: ' || |
|
||
|
9 |
|
GET_CT FROM DUAL; |
|
GET_CT |
FROM DUAL; |
|
||
|
10 |
|
|
|
|
|
SELECT |
'Tr B SELECT-1: ' || |
|
|
11 |
|
|
|
|
|
GET_CT |
FROM DUAL; |
|
|
12 |
|
EXEC DBMS_LOCK.SLEEP(5); |
|
SELECT |
"sb_is_active" |
|
||
|
13 |
|
|
|
|
|
FROM |
"subscriptions" |
|
|
14 |
|
|
|
|
|
WHERE |
"sb_id" = 2; |
|
|
15 |
|
SELECT 'Tr A UPDATE: ' || |
|
|
|
|
||
|
16 |
|
GET_CT FROM DUAL; |
|
|
|
|
||
|
17 |
|
UPDATE |
"subscriptions" |
|
|
|
|
|
18 |
|
SET |
"sb_is_active" = |
EXEC DBMS_LOCK.SLEEP(10); |
19CASE
20WHEN "sb_is_active" = 'Y' THEN 'N'
21WHEN "sb_is_active" = 'N' THEN 'Y'
22END
23WHERE "sb_id" = 2;
24 |
|
SELECT |
'Tr B SELECT-2: ' || |
25 |
|
GET_CT |
FROM DUAL; |
26 |
|
SELECT |
"sb_is_active" |
27 |
|
FROM |
"subscriptions" |
28 |
EXEC DBMS_LOCK.SLEEP(20); |
WHERE |
"sb_id" = 2; |
29 |
|
SELECT |
'Tr B COMMIT: ' || |
30 |
|
GET_CT |
FROM DUAL; |
31 |
|
COMMIT; |
|
32 |
SELECT 'Tr A ROLLBACK: ' || |
|
|
33GET_CT FROM DUAL;
34ROLLBACK;
Работа с MySQL, MS SQL Server и Oracle в примерах © EPAM Systems, RD Dep, 2016–2018 Стр: 455/545

Пример 44: взаимодействие конкурирующих транзакций
Итоговые результаты взаимодействия транзакций таковы.
|
|
|
Уровень изолированности транзакции B |
|||
|
|
|
READ COMMITTED |
SERIALIZABLE |
||
|
|
|
READ ONLY |
READ WRITE |
READ ONLY |
READ WRITE |
|
|
|
Транзакция B |
Транзакция B |
Транзакция B |
Транзакция B |
|
|
|
оба раза чи- |
оба раза чи- |
оба раза чи- |
оба раза чи- |
|
|
|
тает исходное |
тает исходное |
тает исходное |
тает исходное |
|
|
READ ONLY |
(корректное) |
(корректное) |
(корректное) |
(корректное) |
|
|
значение, UP- |
значение, UP- |
значение, UP- |
значение, UP- |
|
|
|
|
||||
A |
READ |
|
DATE в тран- |
DATE в тран- |
DATE в тран- |
DATE в тран- |
|
закции A за- |
закции A за- |
закции A за- |
закции A за- |
||
транзакции |
COMMITTED |
|
||||
|
прещён (R/O) |
прещён (R/O) |
прещён (R/O) |
прещён (R/O) |
||
|
|
|||||
|
|
|
||||
|
|
|
Транзакция B |
Транзакция B |
Транзакция B |
Транзакция B |
|
|
|
оба раза чи- |
оба раза чи- |
оба раза чи- |
оба раза читает |
изолированности |
|
READ WRITE |
тает исходное |
тает исходное |
тает исходное |
исходное (кор- |
|
|
(корректное) |
(корректное) |
(корректное) |
|
|
|
|
|
(корректное) |
(корректное) |
(корректное) |
ректное) значе- |
|
|
|
значение |
значение |
значение |
ние |
|
|
|
Транзакция B |
Транзакция B |
Транзакция B |
Транзакция B |
|
|
|
оба раза чи- |
оба раза чи- |
оба раза чи- |
|
|
|
|
оба раза читает |
|||
|
|
|
тает исходное |
тает исходное |
тает исходное |
|
|
|
|
исходное (кор- |
|||
|
|
|
|
|
|
|
Уровень |
SERIALIZABLE |
READ ONLY |
закции A за- |
закции A за- |
закции A за- |
ректное) значе- |
|
|
|||||
|
|
|
значение, UP- |
значение, UP- |
значение, UP- |
ние, UPDATE в |
|
|
|
DATE в тран- |
DATE в тран- |
DATE в тран- |
|
|
|
|
транзакции A |
|||
|
|
|
|
|
|
|
|
|
|
прещён (R/O) |
прещён (R/O) |
прещён (R/O) |
запрещён (R/O) |
|
|
|
|
|||
|
|
|
Транзакция B |
Транзакция B |
Транзакция B |
Транзакция B |
|
|
|
оба раза чи- |
оба раза чи- |
оба раза чи- |
оба раза читает |
|
|
READ WRITE |
тает исходное |
тает исходное |
тает исходное |
исходное (кор- |
|
|
|
(корректное) |
(корректное) |
(корректное) |
ректное) значе- |
|
|
|
значение |
значение |
значение |
ние |
Работа с MySQL, MS SQL Server и Oracle в примерах © EPAM Systems, RD Dep, 2016–2018 Стр: 456/545

Пример 44: взаимодействие конкурирующих транзакций
Потерянное обновление Oracle может быть исследовано выполнением в двух отдельных сессиях следующих блоков кода:
|
Oracle |
|
Решение 6.2.2.a (код для исследования аномалии потерянного обновления) |
||||||
|
1 |
|
-- Транзакция A: |
|
-- Транзакция B: |
|
|||
|
2 |
|
ALTER SESSION SET |
|
ALTER SESSION SET |
|
|||
|
3 |
|
ISOLATION_LEVEL = {УРОВЕНЬ}; |
|
ISOLATION_LEVEL = {УРОВЕНЬ}; |
|
|||
|
4 |
|
SET TRANSACTION {РЕЖИМ}; |
|
SET TRANSACTION {РЕЖИМ}; |
|
|||
|
5 |
|
SELECT |
'Tr A: ' || |
|
SELECT 'Tr B: ' || |
|
||
|
6 |
|
GET_IDS_AND_ISOLATION_LEVEL |
|
GET_IDS_AND_ISOLATION_LEVEL |
|
|||
|
7 |
|
FROM DUAL; |
|
FROM DUAL; |
|
|||
|
8 |
|
SELECT |
'Tr A START: ' || |
|
SELECT 'Tr B START: ' || |
|
||
|
9 |
|
GET_CT |
FROM DUAL; |
|
GET_CT FROM DUAL; |
|
||
|
10 |
|
SELECT |
'Tr A SELECT: ' || |
|
|
|
|
|
|
11 |
|
GET_CT |
FROM DUAL; |
|
|
|
|
|
|
12 |
|
SELECT |
"sb_is_active" |
|
EXEC DBMS_LOCK.SLEEP(5); |
|
||
|
13 |
|
FROM |
"subscriptions" |
|
|
|
|
|
|
14 |
|
WHERE |
"sb_id" = 2; |
|
|
|
|
|
|
|
|
|
|
|
|
|
||
|
15 |
|
|
|
|
|
SELECT 'Tr B SELECT: ' || |
|
|
|
16 |
|
|
|
|
|
GET_CT FROM DUAL; |
|
|
|
17 |
|
EXEC DBMS_LOCK.SLEEP(10); |
|
|
|
|
||
|
18 |
|
|
|
|
|
SELECT |
"sb_is_active" |
|
|
19 |
|
|
|
|
|
FROM |
"subscriptions" |
|
|
20 |
|
|
|
|
|
WHERE |
"sb_id" = 2; |
|
|
21 |
|
SELECT |
'Tr A UPDATE: ' || |
|
|
|
|
|
|
22 |
|
GET_CT |
FROM DUAL; |
|
|
|
|
|
|
23 |
|
|
|
|
|
|
|
|
|
24 |
|
UPDATE |
"subscriptions" |
|
EXEC DBMS_LOCK.SLEEP(10); |
|
||
25 |
|
SET |
"sb_is_active" = 'Y' |
|
|
|
26WHERE "sb_id" = 2;
27SELECT 'Tr A COMMIT: ' ||
28GET_CT FROM DUAL;
29COMMIT;
30 |
|
|
SELECT |
'Tr B UPDATE: ' || |
31 |
|
|
GET_CT |
FROM DUAL; |
32 |
|
|
UPDATE |
"subscriptions" |
33 |
EXEC DBMS_LOCK.SLEEP(10); |
SET |
"sb_is_active" = 'N' |
|
34 |
|
|
WHERE |
"sb_id" = 2; |
35 |
|
|
SELECT |
'Tr B COMMIT: ' || |
36 |
|
|
GET_CT |
FROM DUAL; |
37 |
|
|
COMMIT; |
|
38 |
SELECT |
'Tr A SELECT AFTER: ' || |
SELECT |
'Tr B SELECT AFTER: ' || |
39 |
GET_CT |
FROM DUAL; |
GET_CT |
FROM DUAL; |
40 |
SELECT |
"sb_is_active" |
SELECT |
"sb_is_active" |
41 |
FROM |
"subscriptions" |
FROM |
"subscriptions" |
42 |
WHERE |
"sb_id" = 2; |
WHERE |
"sb_id" = 2; |
|
|
|
|
|
Работа с MySQL, MS SQL Server и Oracle в примерах © EPAM Systems, RD Dep, 2016–2018 Стр: 457/545

Пример 44: взаимодействие конкурирующих транзакций
Итоговые результаты взаимодействия транзакций таковы.
|
|
|
Уровень изолированности транзакции B |
|||
|
|
|
READ COMMITTED |
SERIALIZABLE |
||
|
|
|
READ ONLY |
READ WRITE |
READ ONLY |
READ WRITE |
|
|
|
UPDATE в |
UPDATE в |
UPDATE в |
UPDATE в |
|
|
READ ONLY |
обеих транзак- |
транзакции A |
обеих транзак- |
транзакции A |
|
|
циях запре- |
запрещён |
циях запре- |
запрещён |
|
|
|
|
||||
A |
|
|
щён (R/O) |
(R/O) |
щён (R/O) |
(R/O) |
|
|
|
|
|
Обновление |
|
транзакции |
READ |
|
|
|
|
|
|
|
|
|
транзакции A |
||
COMMITTED |
|
UPDATE в |
|
UPDATE в |
||
|
|
|
||||
|
|
Обновление |
сохранено, UP- |
|||
|
|
|
транзакции B |
транзакции B |
||
|
|
READ WRITE |
транзакции A |
DATE в тран- |
||
|
|
запрещён |
запрещён |
|||
|
|
|
утеряно |
закции B не вы- |
||
изолированности |
|
|
(R/O) |
(R/O) |
||
|
|
(R/O) |
полнился (см. |
|||
|
|
щён (R/O) |
щён (R/O) |
|||
|
|
|
|
|
|
|
|
|
|
|
|
|
ниже) |
|
|
|
UPDATE в |
UPDATE в |
UPDATE в |
UPDATE в |
|
|
|
обеих транзак- |
транзакции A |
обеих транзак- |
|
|
|
READ ONLY |
транзакции A |
|||
|
|
циях запре- |
запрещён |
циях запре- |
||
|
|
|
запрещён (R/O) |
|||
|
|
|
|
|
|
|
Уровень |
|
|
|
|
|
|
|
|
|
Обновление |
|
сохранено, UP- |
|
|
|
|
|
|
|
Обновление |
|
SERIALIZABLE |
|
UPDATE в |
|
UPDATE в |
транзакции A |
|
|
|
|
|
||
|
|
READ WRITE |
транзакции B |
транзакции A |
транзакции B |
DATE в тран- |
|
|
запрещён |
запрещён |
|||
|
|
|
утеряно |
закции B не вы- |
||
|
|
|
(R/O) |
(R/O) |
||
|
|
|
|
полнился (см. |
||
|
|
|
|
|
|
|
|
|
|
|
|
|
ниже) |
В транзакции B UPDATE приводит к ошибке «ORA-08177: can't serialize access for this transaction», т.к. соответствующая запись заблокирована транзакцией A.
Работа с MySQL, MS SQL Server и Oracle в примерах © EPAM Systems, RD Dep, 2016–2018 Стр: 458/545

Пример 44: взаимодействие конкурирующих транзакций
Неповторяющееся чтение в Oracle может быть исследовано выполнением в двух отдельных сессиях следующих блоков кода:
Oracle Решение 6.2.2.a (код для исследования аномалии неповторяющегося чтения)
|
1 |
|
-- Транзакция A: |
|
-- Транзакция B: |
|
||
|
2 |
|
ALTER SESSION SET |
|
ALTER SESSION SET |
|
||
|
3 |
|
ISOLATION_LEVEL = {УРОВЕНЬ}; |
|
ISOLATION_LEVEL = {УРОВЕНЬ}; |
|
||
|
4 |
|
SET TRANSACTION {РЕЖИМ}; |
|
SET TRANSACTION {РЕЖИМ}; |
|
||
|
5 |
|
SELECT 'Tr A: ' || |
|
SELECT |
'Tr B: ' || |
|
|
|
6 |
|
GET_IDS_AND_ISOLATION_LEVEL |
|
GET_IDS_AND_ISOLATION_LEVEL |
|
||
|
7 |
|
FROM DUAL; |
|
FROM DUAL; |
|
||
|
8 |
|
SELECT 'Tr A START: ' || |
|
SELECT |
'Tr B START: ' || |
|
|
|
9 |
|
GET_CT FROM DUAL; |
|
GET_CT |
FROM DUAL; |
|
|
|
10 |
|
|
|
|
SELECT |
'Tr B SELECT-1: ' || |
|
|
11 |
|
|
|
|
GET_CT |
FROM DUAL; |
|
|
12 |
|
EXEC DBMS_LOCK.SLEEP(5); |
|
SELECT |
"sb_is_active" |
|
|
|
13 |
|
|
|
|
FROM |
"subscriptions" |
|
|
14 |
|
|
|
|
WHERE |
"sb_id" = 2; |
|
|
15 |
|
SELECT 'Tr A UPDATE: ' || |
|
|
|
|
|
|
16 |
|
GET_CT FROM DUAL; |
|
|
|
|
|
|
17 |
|
UPDATE |
"subscriptions" |
|
|
|
|
|
18 |
|
SET |
"sb_is_active" = |
|
|
|
|
|
19 |
|
CASE |
|
|
EXEC DBMS_LOCK.SLEEP(10); |
|
20WHEN "sb_is_active" = 'Y' THEN 'N'
21WHEN "sb_is_active" = 'N' THEN 'Y'
22END
23WHERE "sb_id" = 2;
24SELECT 'Tr A COMMIT: ' ||
25GET_CT FROM DUAL;
26COMMIT;
27 |
SELECT |
'Tr B SELECT-2: ' || |
28 |
GET_CT |
FROM DUAL; |
29 |
SELECT |
"sb_is_active" |
30 |
FROM |
"subscriptions" |
31 |
WHERE |
"sb_id" = 2; |
32 |
SELECT |
'Tr B COMMIT: ' || |
33 |
GET_CT |
FROM DUAL; |
34 |
COMMIT; |
|
Работа с MySQL, MS SQL Server и Oracle в примерах © EPAM Systems, RD Dep, 2016–2018 Стр: 459/545