Т3 считывать значение счета до тех пор, пока транзакция Т4 не будет либо зафиксирована, либо отменена.
Пример проблемы зависимости от нефиксированных результатов представлен в табл. 6.2.
Таблица 6.2 Пример проблемы зависимости от нефиксированных
результатов
Время |
Транзакция Т3 |
Транзакция Т4 |
Поле а1 |
t1 |
|
начало |
100 |
t2 |
|
чтение а1 |
100 |
t3 |
|
а1=а1+100 |
100 |
t4 |
начало |
запись а1 |
200 |
t5 |
чтение а1 |
… |
200 |
t6 |
а1=а1-10 |
откат |
100 |
t7 |
запись а1 |
|
190 |
t8 |
commit |
|
190 |
Проблема несогласованной обработки
Транзакции, которые только считывают информацию из БД, также могут давать неверные результаты, если им будут доступны для чтения промежуточные результаты одновременно выполняющихся и еще не завершенных транзакций, обновляющих информацию в базе. В некоторых случаях эту проблему называют чтением мусора или неповторяемостью чтения.
Проблема несогласованной обработки возникает в тех случаях, когда транзакция считывает несколько значений из БД, после чего вторая транзакция обновляет некоторые из этих значений непосредственно во время выполнения первой транзакции.
Например, Т6 – вычисляет сумму остатков на 3-х счетах, а Т5 – переносит 10 т.р. с одного счета на другой. Тогда Т1 взяла остаток на 1-м и 2-м счетах, а Т2 перенесла 10 т.р. с 1-го счета на 3-й. Итог окажется на 10 т.р. больше, чем нужно. Эту проблему можно устранить, запретив транзакции Т6 считывать
166
значения на счетах, до тех пор, пока транзакция Т5 не зафиксирует выполненные ею обновления.
Еще один пример несогласной обработки представлен в табл. 6.3.
Таблица 6.3
Пример несогласной обработки
Время |
Транзакция |
Транзакция |
Поле |
Поле |
Поле |
Поле |
|
Т5 |
Т6 |
а1 |
в1 |
с1 |
Sum |
||
|
|||||||
t1 |
|
начало |
100 |
50 |
25 |
0 |
|
t2 |
начало |
Sum=0 |
100 |
50 |
25 |
0 |
|
t3 |
чтение а1 |
чтение а1 |
100 |
50 |
25 |
0 |
|
t4 |
а1=а1-10 |
Sum= |
100 |
50 |
25 |
100 |
|
|
|
Sum+а1 |
|
|
|
|
|
t5 |
запись а1 |
чтение в1 |
90 |
50 |
25 |
100 |
|
t6 |
чтение с1 |
Sum= |
90 |
50 |
25 |
150 |
|
|
|
Sum+в1 |
|
|
|
|
|
t7 |
с1=с1+10 |
|
90 |
50 |
25 |
150 |
|
t8 |
запись с1 |
|
90 |
50 |
35 |
150 |
|
t9 |
commit |
чтение с1 |
90 |
50 |
35 |
150 |
|
t10 |
|
Sum= |
90 |
50 |
35 |
185 |
|
|
|
Sum+с1 |
|
|
|
|
|
t11 |
|
commit |
90 |
50 |
35 |
185 |
Упорядочиваемость и восстанавливаемость
Назначение протоколов управления параллельностью состоит в подготовке такого графика выполнения транзакций, который исключит возможность их влияния на результаты работы друг друга. Одно из очевидных решений состоит в выполнении в каждый момент времени только одной транзакции. Однако, назначение многопользовательских СУБД состоит в обеспечении максимальной степени параллельности выполнения транзакций пользователей, поэтому те транзакции, которые не оказывают влияния на работу друг друга, вполне могут выполняться одновременно.
Познакомимся с понятием упорядочиваемости как со средством, способным помочь в выявлении тех транзакций,
167
которые гарантированно не вызовут проблем нарушения согласованности данных при одновременном выполнении.
График – это последовательность запуска операций множества параллельно выполняемых транзакций, сохраняющая очередность выполнения операций в каждой отдельной транзакции.
Последовательный график – график, в котором операции каждой из транзакций выполняются строго последовательно и не могут чередоваться с операциями, выполняемыми в других транзакциях.
Непоследовательный график - график, в котором чередуются операции из некоторого набора одновременно выполняемых транзакций.
Суть упорядочивания состоит в отыскании таких непоследовательных графиков, которые позволят транзакциям выполняться параллельно, но без оказания взаимного влияния друг на друга, и, привести БД в состояние, которое может быть достигнуто при использовании последовательного графика.
В отношении достижения упорядоченности весьма важен порядок выполнения операций чтения и записи данных.
Если две транзакции считывают некоторый элемент данных, они не будут конфликтовать между собой и порядок их выполнения не имеет значения.
Если две транзакции считывают или записывают совершенно независимые элементы данных, они не будут конфликтовать между собой и порядок их выполнения не имеет значения.
Если одна транзакция записывает элемент данных, а другая транзакция этот же элемент данных считывает или записывает, порядок их выполнения имеет существенное значение.
Пример эквивалентных графиков (табл. 6.4): Вариант А – непоследовательный график S1
Вариант Б – непоследовательный график S2, эквивалентный графику S1
168
Вариант |
В |
– |
последовательный |
график |
S3, |
||||
эквивалентный графикам S1 и S2. |
|
|
|
|
|||||
|
|
|
|
|
|
|
Таблица 6.4 |
||
|
Пример эквивалентность графиков |
|
|
|
|||||
A |
|
|
Б |
|
|
В |
|
|
|
|
|
|
|
|
|
|
|
|
|
Т7 |
Т8 |
|
Т7 |
|
Т8 |
Т7 |
|
Т8 |
|
начало |
|
|
начало |
|
|
начало |
|
|
|
чтение а1 |
|
|
чтение а1 |
|
чтение а1 |
|
|
||
запись а1 |
|
|
запись а1 |
|
запись а1 |
|
|
||
|
начало |
|
|
|
начало |
чтение в1 |
|
|
|
|
чтение а1 |
|
|
чтение а1 |
запись в1 |
|
|
||
|
запись а1 |
чтение в1 |
|
commit |
|
|
|
||
чтение в1 |
|
|
|
|
запись а1 |
|
|
начало |
|
запись в1 |
|
|
запись в1 |
|
|
|
чтение а1 |
||
commit |
|
|
commit |
|
|
|
|
запись а1 |
|
|
чтение в1 |
|
|
чтение в1 |
|
|
чтение в1 |
||
|
запись в1 |
|
|
запись в1 |
|
|
запись в1 |
||
|
commit |
|
|
|
commit |
|
|
commit |
|
Поскольку операции записи на счет а1 в Т8 не конфликтует с последующей операцией чтения в1 в Т7, можно изменить порядку выполнения этих операций и получить эквивалентный график S2.
Если поменять порядок выполнения и следующих не конфликтующих между собой операций, то мы получим эквивалентный последовательный график S3.
Если в результате упорядочивания можно получить последовательный график, то этот тип упорядочивания принято называть конфликтным упорядочиванием. В конфликтно упорядоченном графике порядок выполнения любых конфликтующих операций соответствует размещению в последовательном графике.
Для проверки конфликтной упорядоченности можно использовать граф предшествования, который состоит из следующих элементов:
вершин, соответствующих каждой из транзакций;
169
направленных ребер Ti->Tj, где транзакция Ti считывает значение элемента, записанного транзакцией Tj;
направленных ребер Ti->Tj, где транзакция Tj записывает значение в элемент данных после того, как он был считан транзакцией Ti.
Если граф предшествования содержит петли, то соответствующий ему график не является конфликтно упорядоченным.
Пример графика не являющегося конфликтно упорядоченным
Рассмотрим две транзакции, график выполнения которых представлен в табл. 6.5.
Таблица 6.5 Пример неконфликтно упорядорченных графиков
Транзакция |
Транзакция Т2 |
Т1 |
|
начало |
|
чтение а1 |
|
а1=а1+100 |
|
запись а1 |
начало |
|
чтение а1 |
|
а1=а1*1.1 |
|
запись |
|
в1=в1*1.1 |
|
запись в1 |
чтение в1 |
commit |
в1=в1-100 |
|
запись в1 |
|
commit |
|
Здесь в транзакции Т1 100 рублей передается со счета в1 на счет а1. Транзакция Т2 увеличивает текущее значение каждого из этих счетов на 10%. Граф предшествования для данного графика представлен на рис. 6.1.
170