Главная » SQL, Базы данных » УРОВНИ ИЗОЛЯЦИИ

0

Упорядочиваемость гарантирует изолированность транзакций, в той трактовке этого термина, которая применяется при описании свойств ACID. Одним из непосредственных и весьма благоприятных следствий из этого факта является то, что если все графики

—    упорядочиваемые,  то  прикладной программист,  разрабатывая  код  для  любой конкретной транзакции А, не должен обращать абсолютно никакого внимания на тот факт, что одновременно с ней в системе может выполняться некоторая другая транзакция в.

Но можно также утверждать, что протоколы, применяемые для обеспечения упорядочиваемое™, снижают степень распараллеливания, или общую производительность системы, до неприемлемых уровней. Поэтому на практике в  системах обычно поддерживаются

целый ряд других уровней "изоляции" (этот термин заключен в кавычки, поскольку любой уровень ниже максимального означает, что транзакция в конечном итоге не является в полном смысле слова изолированной от других, как показано ниже).

Уровень изоляции применительно к данной конкретной транзакции можно  определить как степень постороннего вмешательства, которую  рассматриваемая  транзакция готова выдерживать в ходе параллельного выполнения транзакций. А если должна гарантироваться  упорядочиваемость,  то  единственно  возможной  степенью  вмешательства, которую следует допускать по отношению к любой транзакции,  безусловно, является полное отсутствие какого-либо вмешательства! Иными словами, уровень изоляции должен быть максимально возможным, поскольку в противном случае невозможно будет в общем гарантировать наличие правильных, восстанавливаемых и не  допускающих каскадных откатов графиков. Но остается неоспоримым фактом то, что во многих системах,

как уже было сказано, обычно поддерживаются уровни изоляции меньше максимального,

и данный вопрос кратко рассматривается в настоящем разделе.

Может быть определено по меньшей мере пять разных уровней изоляции, но в [16.10],

в стандарте SQL и в СУБД DB2 поддерживаются лишь четыре. Вообще говоря, чем выше уровень изоляции, тем меньше степень вмешательства транзакций в работу друг друга (и тем ниже степень распараллеливания), а чем ниже уровень изоляции, тем больше степень вмешательства (и выше степень распараллеливания). В  качестве иллюстрации рассмотрим два уровня, поддерживаемых в СУБД DB2, — стабильность курсора и повторяемое чтение. Максимальным уровнем является  повторяемое чтение (Repeatable Read — RR); если все транзакции действуют на  этом уровне, то все графики становятся упорядочиваемыми. В отличие от этого, при использовании другого уровня, а именно стабильности курсора (Cursor Stability — CS) соблюдаются следующие условия:

■если транзакция А получает возможность обратиться к некоторому кортежу6   t  и в результате

■     приобретает блокировку на t, а затем

■     освобождает структуры адресации, применяемые для доступа к" кортежу t без его обновления, и поэтому

6  Такая возможность в транзакции появляется благодаря такой установке курсора, когда он указывает на кортеж (как было описано в главе 4), отсюда и происходит название "стабильность  курсора". Но в целях уточнения необходимо указать, что в СУБД DB2 приобретаемая блокировка  Т1 кортежа t фактически является блокировкой "обновления" (update — U), а не блокировкой S (см. [4.21]).

■     не расширяет свою блокировку до уровня X, то

■     данная блокировка может быть освобождена без ожидания конца транзакции.

Но следует учитывать, что теперь некоторая другая транзакция в может обновить кортеж t и зафиксировать изменение. Если в дальнейшем транзакция А возвратится на некоторый предыдущий этап своей работы и снова прочитает кортеж t (следует отметить, что при этом происходит нарушение протокола двухфазной блокировки!), то обнаружит внесенное изменение и поэтому  фактически столкнется с несовместимым состоянием базы данных. С другой стороны, при повторяемом чтении (RR) все блокировки кортежей (а не только  блокировки X) удерживаются до конца транзакции и поэтому только что указанная проблема не возникает.

Из этого следуют приведенные ниже выводы.

1.  Указанная проблема является не единственной, которая может возникнуть при использовании уровня CS; мы здесь привели ее описание лишь потому, что она является наиболее очевидной. Но, к сожалению, из этого описания следует, что уровень RR якобы требуется лишь в том сравнительно маловероятном случае, если в некоторой определенной транзакции потребуется дважды считывать один и тот же кортеж. С другой стороны, имеются весомые доводы в пользу того, что уровень RR всегда является более приемлемым по сравнению с CS; транзакция, выпол няемая в условиях применения CS, не является двухфазной и поэтому (как было описано в предыдущем разделе) ее упорядочиваемость больше нельзя гарантиро вать. Но другой весомый контрдовод состоит в том, что уровень CS обеспечивает большую степень распараллеливания, чем RR (тем не менее, справедливость этого утверждения является вероятной, но не обязательной).

2.  Создается впечатление, что на практике часто недостаточно учитывается тот факт, что при использовании уровня CS упорядочиваемость не может гарантироваться. Поэтому следует еще раз подчеркнуть, что справедливо такое утверждение: "Если транзакция т действует на уровне изоляции меньше максимального, то нельзя больше гарантировать, что при выполнении т параллельно с другими транзакция ми она переведет базу данных из одного правильного состояния в другое правиль ное состояние".

3.  В любой реализации, которая поддерживает любой уровень изоляции ниже мак симального, должны быть, как правило, предусмотрены некоторые средства яв ного управления параллельностью, позволяющие пользователям создавать свои приложения так, чтобы гарантировалась безопасность эксплуатации базы данных в отсутствие подобных гарантий со стороны самой системы (обычно явно задан ные операторы LOCK). Например, в СУБД DB2 предусмотрен явно заданный опе ратор LOCK   TABLE, который дает возможность пользователям, работающим на уровне меньше максимального, приобретать явные блокировки, превосходящие те, которые приобретаются в DB2 автоматически для соблюдения требований те кущего уровня. (Кстати, следует отметить, что в стандарте SQL не предусмотрены подобные явно заданные механизмы управления параллельностью, как описано в разделе 16.11.)

Кроме того, необходимо учитывать, что приведенное выше описание уровня RR как максимального уровня изоляции относится к реализации повторяемого чтения в СУБД

DB2. К сожалению, в стандарте SQL термин повторяемое чтение используется для обозначения уровня изоляции, который является строго более низким, чем максимальный уровень (об этом также сказано в разделе 16.11).

Фантомы

Одной из особых проблем, которая может возникнуть, если транзакции действуют на уровне изоляции меньше максимального, является так называемая  проблема фантомов. Рассмотрим приведенный ниже пример (он является довольно надуманным, но вполне позволяет проиллюстрировать рассматриваемое понятие).

■     Прежде всего, предположим, что в транзакции А вычисляется средний остаток на всех счетах, принадлежащих клиенту Джо. Допустим, что в настоящее время име ются три таких счета и на каждом из них остаток составляет 100 долл. Поэтому транзакция А просматривает три счета, в ходе своего выполнения приобретает на них разделяемые блокировки и получает результат (100 долл.).

■     А теперь предположим, что выполняется параллельная транзакция в, в результате которой в базу данных вводится еще один счет клиента Джо, с остатком 200 долл. Для определенности допустим, что новый счет вводится после того, как в транзак ции А было вычислено среднее значение, равное 100 долл. Предположим также, что сразу же после введения нового счета в транзакции в происходит фиксация (и освобождение исключительной блокировки нового счета, которой она владела).

■     Затем допустим, что было принято решение снова воспользоваться транзакцией А для просмотра счетов клиента Джо, подсчета их количества и суммирования их ос татков, а затем деления суммы остатков на количество счетов (возможно, потому что пользователь захотел определить, действительно ли полученное раньше сред нее значение равно сумме, деленной на количество). На данный момент обнару живаются четыре счета вместо трех, а полученный результат равен 125 долл. вме сто 100 долл.!

Итак, в данном случае в обоих транзакциях применялась строгая двухфазная блокировка и все же случилось что-то неправильное, а именно: в транзакции А было обнаружено то, чего не существовало при первом ее выполнении, — фантом. Вследствие этого упорядочиваемость была нарушена (очевидно, что в данном случае чередующееся выполнение не эквивалентно ни последовательности "вначале А, затем в", ни последовательности "вначале в, затем А").

Но заслуживает особого внимания то, что рассматриваемая здесь проблема не имеет ничего общего с двухфазной блокировкой как таковой. Скорее, эта проблема состоит в том, что в транзакции А не было заблокировано то, что логически должно было быть заблокировано; вместо блокировки лишь трех имеющихся счетов клиента Джо в ней фактически нужно было заблокировать множество всех счетов, принадлежащих Джо  или, иными словами, счетов, соответствующих предикату "владелец счета — Джо" (см. [16.6] и [16.13])7. Если бы можно было обеспечить такую возможность, то транзакции в пришлось бы перейти в состояние ожидания после осуществления в ней попытки ввести новый

7 Эту мысль можно также выразить таким образом, что в транзакции А необходимо было заблокировать саму возможность отрицания того факта, что Джо не принадлежат какие-либо иные счета, кроме рассматриваемых.

счет (поскольку в, безусловно, пришлось бы затребовать блокировку на этот новый счет, а такая блокировка вошла бы в противоречие с блокировкой, принадлежащей транзакции А). Хотя по причинам, описанным в [15.12], в большинстве  современных систем не поддерживается блокировка предикатов как таковая, в них все равно, как правило, удается избежать возникновения фантомов благодаря  блокировке пути доступа, который используется для обращения к рассматриваемым данным. Например, если в случае использования тех счетов, которые принадлежат Джо, путем доступа является индекс на имени клиента, то система может заблокировать запись в этом индексе, относящуюся к клиенту Джо. Такая блокировка предотвращает возникновение фантомов, поскольку для создания такого фантома требуется обновление пути доступа (в данном примере записи индекса) и поэтому приобретение блокировки X на такой путь доступа. Дополнительные сведения на эту тему приведены в [15.12].

Источник: Дейт К. Дж., Введение в системы баз данных, 8-е издание.: Пер. с англ. — М.: Издательский дом «Вильямс», 2005. — 1328 с.: ил. — Парал. тит. англ.

По теме:

  • Комментарии