В первом примере (рис. 15.3) транзакция A в момент времени t2 встречается с невыполненным обновлением (оно также называется невыполненным изменением). Затем это обновление отменяется в момент времени t3. Таким образом, транзакция A выполняется на основе фальшивого предположения, что кортеж р имеет некоторое значение в момент времени t2, тогда как на самом деле он имеет некоторое значение, существовавшее еще в момент времени t1. В итоге после выполнения транзакции A будет получен неверный результат. Кроме того, обратите внимание, что отмена выполнения транзакции B может произойти не по вине транзакции B, а, например, в результате краха системы. (К этому времени выполнение транзакции A может быть уже завершено, а потому крушение системы не приведет к отмене выполнения транзакции A.)
Транзакция A | Время | Транзакция B |
– | t1 | Обновление кортежа р |
Извлечение кортежа р | t2 | – |
– | t3 | Отмена выполнения транзакции |
рис. 15.3. Транзакция A становится зависимой от невыполненного изменения в момент времени t2.
Транзакция A | Время | Транзакция B |
– | t1 | Обновление кортежа р |
Обновление кортежа р | t2 | – |
– | t3 | Отмена выполнения транзакции |
рис. 15.4. Транзакция A обновляет невыполненное изменение в момент времени t2, и результаты этого обновления утрачиваются в момент времени t3.
Второй пример, приведенный на рис. 15.4, иллюстрирует другой случай. Не только транзакция A становится зависимой от изменения, не выполненного в момент времени t2, но также в момент времени t3 фактически утрачивается результат обновления, поскольку отмена выполнения транзакции B в момент времени t3 приводит к восстановлению кортежа р к исходному значению в момент времени t1. Это еще один вариант проблемы потери результатов обновления.
На рис. 15.5 показаны транзакции A и B, которые выполняются для кортежей со счетами (табл. 9.1). При этом транзакция A суммирует балансы, транзакция B производит перевод суммы 10 со счета 3 на счет 1. Полученный в итоге транзакции A результат 110, очевидно, неверен, и если он будет записан в базе данных, то в ней может возникнуть проблема несовместимости. В таком случае говорят, что транзакция A встретилась с несовместимым состоянием и на его основе был выполнен несовместимый анализ. Обратите внимание на следующее различие между этим примером и предыдущим: здесь не идет речь о зависимости транзакции A от транзакции B, так как транзакция B выполнила все обновления до того, как транзакция A извлекла СЧЕТ 3.
табл. 15.1 Остатки на счетах до выполнения транзакций.
Счет | СЧЕТ 1 | СЧЕТ 2 | СЧЕТ 3 |
Остаток | 40 | 50 | 30 |
Транзакция A | Время | Транзакция B |
Извлечение кортежа СЧЕТ 1: СУММА = 40 | t1 | – |
Извлечение кортежа СЧЕТ 1: СУММА = 90 | t2 | – |
– | t3 | Извлечение кортежа СЧЕТ 3: |
– | t4 | Обновление кортежа СЧЕТ 3: 30 ® 20 |
– | t5 | Извлечение кортежа СЧЕТ 1: |
– | t6 | Обновление кортежа СЧЕТ 1: 40 ® 50 |
– | t7 | Завершение выполнения транзакции |
Извлечение кортежа СЧЕТ 3: СУММА = 110 (а не 120) | t8 | – |
рис. 15.5. Транзакция A выполнила несовместимый анализ.
Описанные выше проблемы могут быть разрешены с помощью методики управления параллельным выполнением процессов под названием блокировка. Ее основная идея очень проста: в случае, когда для выполнения некоторой транзакции необходимо, чтобы некоторый объект (обычно это кортеж базы данных) не изменялся непредсказуемо и без ведома этой транзакции (как это обычно бывает), такой объект блокируется. Таким образом, эффект блокировки состоит в том, чтобы "заблокировать доступ к этому объекту со стороны других транзакций", а значит, предотвратить непредсказуемое изменение этого объекта. Следовательно, первая транзакция в состоянии выполнить всю необходимую обработку с учетом того, что обрабатываемый объект остается в стабильном состоянии настолько долго, насколько это нужно.
Предположим, что в системе поддерживается два типа блокировок: блокировка без взаимного доступа (монопольная блокировка), называемая Х-блокировкой (X locks – exclusive locks), и блокировка с взаимным доступом, называемая S-блокировкой (S locks - Shared locks). Замечание. Х- и S-блокировки иногда называют блокировками записи и чтения соответственно. Предположим, что Х- и S-блокировки единственно возможные, хотя в коммерческих системах существуют блокировки других типов. Кроме того, допустим, что в кортежи являются единственным типом "блокируемого объекта", хотя опять же н в коммерческих системах могут блокироваться и другие объекты. Ниже показано функционирование механизма блокировок.
1. Если транзакция A блокирует кортеж р без возможности взаимного доступа (Х‑блокировка), то запрос другой транзакции B с блокировкой этого кортежа p будет отменен.
2. Если транзакция A блокирует кортеж р с возможностью взаимного доступа (S‑блокировка), то:
2.1. запрос со стороны некоторой транзакции B на Х‑блокировку кортежа будет отвергнут;
2.2. запрос со стороны некоторой транзакции B на S‑блокировку кортежа р будет принят (т.е. транзакция B также будет блокировать кортеж р с помощью S‑блокировки).
Эти правила можно наглядно представить в виде матрицы совместимости, показанной на рис. 15.6, и интерпретировать ее следующим образом. Рассмотрим некоторый кортеж р и предположим, что транзакция A блокирую кортеж р различными типами блокировки (это обозначено соответствующими символами S и X, а отсутствие блокировки — прочерком). Предположим также, что некоторая транзакция B запрашивает блокировку кортежа р, что обозначено в первом слева столбце матрицы на рис. 15.6 (для полноты картины в таблице также приведен случай "отсутствия блокировки"). В других ячейках матрицы символ N обозначает конфликтную ситуацию (запрос со стороны транзакции B не может быть удовлетворен, и сама эта транзакция переходит в состояние ожидания), a Y – полную совместимость (запрос со стороны транзакции B удовлетворен). Очевидно, что эта матрица является симметричной.
X | S | – | |
X | N | N | Y |
S | N | Y | Y |
– | Y | Y | Y |
рис. 15.6. Матрица совместимости для Х- и S-блокировки.
Введем протокол доступа к данным, который на основе введения только что описанных Х- и S-блокировки позволяет избежать возникновения проблем параллелизма.
1. Транзакция, предназначенная для извлечения кортежа, прежде всего должна наложить S‑блокировку на этот кортеж.
2. Транзакция, предназначенная для обновления кортежа, прежде всего должна наложить Х–блокировку на этот кортеж. Иначе говоря, если, например, для последовательности действий типа извлечение/обновление для кортежа уже задана S-блокировка, то ее необходимо заменить Х‑блокировкой. Блокировки в транзакциях обычно задаются неявным образом: например, запрос на "извлечение кортежа" является неявным запросом с S-блокировкой, а запрос на "обновление кортежа" – неявным запросом с Х‑блокировкой соответствующего кортежа. При этом под термином "обновление" (как и ранее) подразумеваются помимо самих операций обновления также операции вставки и удаления.
3. Если запрашиваемая блокировка со стороны транзакции B отвергается из-за конфликта с некоторой другой блокировкой со стороны транзакции A, то транзакция B переходит в состояние ожидания. Причем транзакция B будет находиться в состоянии ожидания до тех пор, пока не будет снята блокировка, заданная транзакцией A. В системе обязательно должны быть предусмотрены способы устранения бесконечно долгого состояния ожидания транзакции B.
4. Х–блокировки сохраняются вплоть до конца выполнения транзакции (до операции "завершение выполнения" или "отмена выполнения"). S‑блокировки также обычно сохраняются вплоть до этого момента.
Рассмотрим решение проблем параллелизма с помощью механизма блокировок.
На рис. 15.7 приведена измененная версия процесса, показанного на рис. 15.2, с учетом применения протокола блокировки для чередующихся операций. Операция обновления для транзакции A в момент времени t3 не будет выполнена, поскольку она является неявным запросом с заданием Х-блокировки для кортежа р, а этот запрос вступает в конфликт с S-блокировкой, уже заданной транзакцией B. Таким образом, транзакция A переходит в состояние ожидания. По аналогичным причинам транзакция B переходит в состояние ожидания в момент времени t4.Обновления теперь не утрачиваются, однако возникает новая проблема – бесконечное ожидание или тупиковая ситуация. Способы решения этой проблемы рассматриваются ниже.
Транзакция A | Время | Транзакция B |
Извлечение кортежа р (задание S-блокировки для p) | t1 | – |
– | t2 | Извлечение кортежа р (задание S-блокировки для p) |
Обновление кортежа р (задание X-блокировки для p) | t3 | – |
Ожидание | t4 | Обновление кортежа р (задание X-блокировки для p) |
Ожидание | Ожидание |
рис. 15.7. Хотя обновления не утрачиваются, но в момент времени t4 возникает тупиковая ситуация.