Дейт К. Д27 Руководство по реляционной субд db2/ Пер с англ и предисл. М. Р. Когаловского
Вид материала | Руководство |
- Рич Р. К. Политология. Методы исследования: Пер с англ. / Предисл. А. К. Соколова, 6313.17kb.
- Рич Р. К. Политология. Методы исследования: Пер с англ. / Предисл. А. К. Соколова, 6313.29kb.
- Сорокин П. А. С 65 Человек. Цивилизация. Общество / Общ ред., сост и предисл., 11452.51kb.
- The guilford press, 6075kb.
- The guilford press, 6075.4kb.
- Курс лекций "Базы данных и субд" Ульянов В. С. Лекция. Целостная часть реляционной, 213.79kb.
- Дэвид Дайчес, 1633.42kb.
- Mathematics and the search for knowledge morris kline, 498.28kb.
- Лекция №1: Стандарты языка sql, 1420.56kb.
- Курс лекций "Базы данных и субд" Ульянов В. С. Лекция. Манипулирование реляционными, 276.31kb.
11.4. ТРИ ПРОБЛЕМЫ, СВЯЗАННЫЕ С ПАРАЛЛЕЛИЗМОМ
DB2 представляет собой совместно используемую систему, т. е. это система, позволяющая любому числу транзакций одновременно осуществлять доступ к одной и той же базе данных. Для каждой такой системы требуется некоторого рода механизм управления параллельными процессами, который бы обеспечивал, чтобы параллельно используемые транзакции не мешали действию друг друга и, конечно, система DB2 включает такой механизм (по существу, механизм блокирования). Для читателей, возможно, незнакомых с проблемами, которые могут возникнуть при отсутствии такого механизма (другими словами, с проблемами, которые способен решать такой механизм), эти проблемы в общих чертах поясняются в данном разделе. Обсуждению возможностей указанного механизма специально в системе DB2 будут посвящены разделы 11.5–11.7. Читатели, уже хорошо знакомые с основными идеями управления параллельными процессами, могут сразу же обратиться к этим разделам.
Имеется, по существу, три случая ошибочного исполнения (И соответственно три связанные с ними проблемы (см. ниже).— Примеч. пер.), т. е. три ситуации, когда транзакция, корректная сама по себе, может продуцировать тем не менее ошибочный результат из-за вмешательства со стороны некоторой другой транзакции, конечно, при отсутствии подходящего механизма управления. Заметим, между прочим, что транзакция, осуществляющая вмешательство, также может быть сама по себе корректна. Речь идет, таким образом, о чередовании операций из двух корректных транзакций, которое продуцирует в целом некорректный результат.
К указанным выше проблемам относятся:
1. Проблема утраченного обновления.
- 2. Проблема зависимости от незафиксированных обновлений.
- 3. Проблема анализа на противоречивость.
Рассмотрим поочередно каждую из них.
Проблема утраченного обновления
Рассмотрим ситуацию, показанную на рис. 11.1. Предполагается, что этот рисунок читается следующим образом: транзакция А осуществляет выборку некоторой записи R в момент времени t1.
-
Транзакция А
Время
Транзакция В
—
—
—
—
FETCH R
t1
—
—
—
—
t2
FETCH R
—
—
UPDATE R
t3
—
—
—
—
t4
UPDATE R
—
—
Рис. 11.1. Транзакция А утрачивает обновление в момент t4
Транзакция В осуществляет выборку той же самой записи R в момент времени t2. Транзакция А обновляет эту запись в момент t3 исходя из значений, «увиденных» в момент времени t1, а транзакция В обновляет ту же запись в момент времени t4, исходя из значений, «увиденных» в момент t2, являющихся теми же самыми, что и значения, «увиденные» в момент t1. Обновление, осуществляемое транзакцией А, утрачивается в момент t4, поскольку транзакция В перекрывает его своим обновлением, даже на него «не глядя».
Проблема зависимости от незафиксированных обновлений
Проблема зависимости от незафиксированных обновлений возникает в случае, если одной транзакции разрешается осуществлять выборку или, хуже того, обновление записи, которая уже была обновлена другой транзакцией, но это обновление еще не было зафиксировано этой другой транзакцией. Поскольку оно еще не было зафиксировано, всегда существует возможность, что оно никогда не будет зафиксировано, и вместо этого произойдет откат. В результате первая транзакция «увидит» некоторые данные, которые теперь больше не существуют, и в некотором смысле «никогда» не существовали. Рассмотрим рис. 11.2 и 11.3.
-
Транзакция А
Время
Транзакция В
—
—
—
—
—
t1
UPDATE R
—
—
FETCH R
t2
—
—
—
—
t3
ROLLBACK
—
Рис. 11.2. Транзакция А становится зависимой от незафиксированных изменений в момент t2
-
Транзакция А
Время
Транзакция В
—
—
—
—
—
t1
UPDATE R
—
—
UPDATE R
t2
—
—
—
—
t3
ROLLBACK
—
Рис. 11.3. Транзакция А обновляет незафиксированное изменение в момент t2 и утрачивает это обновление в момент t3
В первом из этих примеров (рис. 11.2) транзакция А «видит» незафиксированное обновление (или незафиксированное изменение) в момент t2. Затем это обновление в момент t3 аннулируется. Следовательно, транзакция А выполняется при ошибочном предположении, а именно при предположении, что запись R имеет значение, «увиденное» в момент t2, тогда как на самом деле она вообще имеет значение, которое имела до момента t1. В результате вполне возможно, что транзакция А будет продуцировать некорректный результат. Отметим, между прочим, что откат транзакции В (по команде ROLLBACK) может и не являться следствием каких-либо ошибок в В. Он может быть, например, результатом отказа системы. (И транзакция А уже может завершиться к этому времени. В результате отказ системы не вызовет необходимости издать команду ROLLBACK также и для А.)
Второй пример (рис. 11.3) еще хуже. Транзакция А не только становится зависимой от незафиксированного изменения данных в момент t2, но и фактически утрачивает обновление в момент t3, поскольку операция ROLLBACK в момент t3 заставляет восстановить для записи R ее значение, которое она имела в момент t1. Это другой вариант проблемы утраченного обновления.
Проблема анализа на противоречивость
Рассмотрим рис. 11.4, на котором показаны две транзакции А и В, оперирующие записями счетов. Транзакция А суммирует остатки на счетах, транзакция В переносит сумму 10 со счета 3 на счет 1. Продуцируемый А результат 110, очевидно, некорректен, и если бы А должна была записать этот результат в базу данных, она оставила бы фактически базу данных в противоречивом состоянии. Будем говорить, что А «видела» противоречивое состояние базы данных и поэтому провела анализ на противоречивость. Отметим различие между данным и предыдущим примером. Здесь нет проблемы зависимости А от незафиксированных изменений, поскольку В фиксирует все произведенные ею обновления прежде, чем А «увидит» запись СЧЕТА 3.
-
СЧЕТ 1
СЧЕТ 2
СЧЕТ 3
40
50
30
Транзакция А
Время
Транзакция В
—
—
—
—
FETCH СЧЕТ 1 (40):
СУММА == 40
t1
—
—
—
FETCH СЧЕТ 2 (50): СУММА = 90
—
t2
—
—
—
—
t3
FETCH СЧЕТ 3 (30)
—
—
—
t4
UPDATE СЧЕТ 3: 3020
—
—
—
t5
FETCH СЧЕТ 1 (40)
—
—
—
t6
UPDATE СЧЕТ 1: 4050
—
—
—
t7
COMMIT
—
FETCH СЧЕТ 3 (20): СУММА=110, а не 120
t8
Рис. 11.4. Транзакция А осуществляет анализ на противоречивость
11.5. КАК СИСТЕМА DB2 РЕШАЕТ ЭТИ ТРИ ПРОБЛЕМЫ ПАРАЛЛЕЛЬНЫХ ПРОЦЕССОВ
Как уже упоминалось в начале предыдущего раздела, механизм управления параллельными процессами системы DB2, подобно предназначенным для этого механизмам большинства других доступных в настоящее время систем, основан на технике, называемой блокированием. Главная идея блокирования проста: если транзакции нужны гарантии, что некоторый объект, в котором она заинтересована—обычно запись базы данных, не будет изменен каким-либо непредсказуемым образом в течение требуемого промежутка времени, она устанавливает блокировку этого объекта. Результат блокировки заключается в том, чтобы изолировать этот объект от других транзакций и, в частности, предотвратить его изменение средствами этих транзакций. Для первой транзакции, таким образом, имеется возможность выполнять предусмотренную в ней обработку, располагая определенными знаниями о том, что объект в запросе будет оставаться в стабильном состоянии до тех пор, пока данная транзакция этого пожелает.
Перейдем теперь к более детальному рассмотрению принципа действия блокирования конкретно для системы DB2. Начнем с некоторых упрощающих предположений.
1. Предполагается, что единственным видом объектов, подверженных действию механизма блокирования, является запись базы данных, т. е. строка базовой таблицы. Вопрос о блокировании объектов других видов отложим до раздела 11.6.
2. Будут обсуждаться только два вида блокировок, а именно — монопольные блокировки (тип X) и совместные блокировки (тип S) (Названия типов блокировок Х и S происходят от английских слов Shared (совместный) и exclusive (монопольный).—Примеч. пер.). В некоторых системах существуют другие типы блокировок. Фактически сама система DB2 внутренне поддерживает некоторые дополнительные их типы, но для пользователей в DB2 представляют интерес только блокировки типов Х и S.
3. Здесь рассматриваются только операции уровня записей (FETCH, UPDATE CURRENT и т. д.). Операции уровня множеств для целей блокирования могут рассматриваться как краткое обозначение соответствующих последовательностей операций уровня записей.
Теперь приступим к детальному рассмотрению вопроса.
1. Прежде всего если транзакция А устанавливает монопольную блокировку (тип X) записи R, то запрос из транзакции В на любого типа блокировку записи R приведет к тому, что В перейдет в состояние ожидания. Транзакция В будет находиться в этом состоянии до тех пор, пока не будет снята блокировка, установленная транзакцией А.
2. Далее, если транзакция А устанавливает совместную блокировку (тип S) записи R, то: а) запрос из транзакции В на блокировку типа Х записи R заставит В перейти в состояние ожидания, и В будет находиться в этом состоянии до тех пор, пока не будет снята блокировка, установленная транзакцией А; б) запрос из транзакции В на блокировку типа S записи R будет удовлетворен, т. е. теперь транзакция В будет также удерживать блокировку типа S записи R.
Сказанное можно удобно резюмировать с помощью матрицы совместимости (рис. 11.5). Эта матрица интерпретируется следующим образом. Рассмотрим некоторую запись R. Предположим, что в настоящее время А удерживает блокировку R, тип которой указывается элементами в заголовках столбцов (тире обозначает отсутствие блокировки). Пусть теперь некоторая другая транзакция В издает запрос на блокировку R, тип которой указывается в левом столбце таблицы. Здесь для полноты снова включен случай «отсутствие блокировки». Тогда значение «N» на пересечении соответствующих столбца и строки матрицы указывает на конфликт—запрос транзакции В не может быть удовлетворен, и В переходит в состояние ожидания. Значение «Y» указывает совместимость — запрос В удовлетворяется. Очевидно, что приведенная матрица симметрична.
| Х | S | — |
Х S — | N N Y | N Y Y | Y Y Y |
Рис. 11.5. Матрица совместимости типов блокировки
Продолжим наше рассмотрение.
3. Запросы транзакций на блокировку записей всегда являются неявными. Когда транзакция успешно осуществляет выборку записи (операция FETCH), она автоматически устанавливает блокировку типа S этой записи. Когда транзакция успешно обновляет запись, она автоматически устанавливает блокировку типа Х этой записи. Если же она уже удерживала блокировку типа Х для этой записи, как это будет происходить в случае последовательности операций FETCH . . . UPDATE, то операция UPDATE «повышает» блокировку типа S до уровня X.
4. Блокировки типа Х удерживаются до следующей точки синхронизации. Блокировки типа S обычно также удерживаются до этого момента времени (см. однако обсуждение вопроса об уровне изоляции в разделе 11.6).
Теперь мы имеем возможность уяснить, каким образом в системе DB2 решаются три проблемы, описанные в предыдущем разделе. Снова будем рассматривать их поочередно.
Проблема утраченного обновления
Рис. 11.6 представляет собой модифицированный вариант рис. 11.1, показывающий, что произошло бы при параллельном" исполнении приведенных на рисунке транзакций под управлением механизма блокирования, предусмотренного в системе DB2.
-
Транзакция А
Время
Транзакция В
—
—
—
—
FETCH R
t1
—
(установить блокировку
—
типа S для R)
—
—
t2
FETCH R
—
(установить блокировку
—
типа S для R)
—
—
UPDATE R
t3
—
(запрос блокировки
—
типа Х для R)
—
ждать
t4
UPDATE R
ждать
(запрос блокировки
ждать
типа Х для R)
ждать
ждать
ждать
ждать
ждать
ждать
Рис. 11.6. Не утрачиваются никакие обновления, но в момент t4 возникает тупиковая ситуация
Легко видеть, что запрос транзакции А в момент t3 на операцию UPDATЕ не принимается, поскольку это неявный запрос на блокировку типа Х для записи R, и такой запрос противоречит блокировке типа S, уже установленной транзакцией В. Поэтому А переходит в состояние ожидания. По аналогичным причинам транзакция В переходит в состояние ожидания в момент t4. Теперь обе транзакции не могут быть продолжены. Поэтому не возникает вопрос о том, что какое-либо обновление может быть утрачено. Таким образом, в системе DB2 проблема утраченного обновления решается путем сведения ее к другой проблеме, но это, по крайней мере, действительно решает первоначальную проблему! Эта новая проблема называется проблемой тупиковых ситуаций. Решение этой проблемы в системе DB2 обсуждается в разделе 11.7.
Проблема зависимости от незафиксированных обновлений
Рис. 11.7 и 11.8 являются модифицированными вариантами рис. 11.2 и 11.3 соответственно, показывающими, что произошло бы при параллельном исполнении представленных на этих рисунках транзакций под управлением механизма блокирования, используемого в системе DB2. Нетрудно видеть, что операция транзакции А, запрашиваемая в момент t2 (FETCH—на рис. 11.7 и UPDATE—на рис. 11.8), в обоих случаях не выполняется, поскольку это неявный запрос на блокировку R, а такой запрос вступает в конфликт с уже установленной транзакцией В блокировкой типа X. Поэтому А переходит в состояние ожидания. Она остается в этом состоянии до тех пор, пока В не достигнет точки синхронизации, выполняя операцию COMMIT или ROLLBACK. При этом установленная транзакцией В блокировка снимается, и А получает возможность продолжать исполнение. В этот момент А «видит» зафиксированное значение — либо значение, предшествующее исполнению В, если В завершается операцией ROLLBACK, либо значение, соответствующее успешному завершению В, в противном случае. В любом случае А больше не зависит от незафиксированных обновлений.
-
Транзакция А
Время
Транзакция В
—
—
—
—
—
t1
UPDATE R
—
(запрос блокировки
—
типа Х для R)
FETCH R
t2
—
(запрос блокировки
—
типа S для R)
—
ждать
—
t3
точка синхронизации
ждать
(снять блокировку типа
Х для R)
ждать
—
повторно: FETCH R
t4
(установить блокировку
типа S для R)
—
Рис. 11.7. Предотвращается ситуация, когда транзакция А «увидела» бы в момент t2 незафиксированное изменение
-
Транзакция А
Время
Транзакция В
—
—
—
—
—
t1
UPDATE R
—
(установить блокировку
—
типа Х для R)
UPDATE R
t2
—
(запрос блокировки
—
типа Х для R)
—
ждать
—
ждать
t3
точка синхронизации
ждать
(снять блокировку типа
Х для R)
повторно: UPDATE R
t4
(установить блокировку
типа Х для R)
Рис. 11.8. Предотвращается ситуация, когда транзакция А обновила бы в момент t2 незафиксированное изменение
Проблема анализа на противоречивость
-
СЧЕТ 1
СЧЕТ 2
СЧЕТ 3
40
50
30
Транзакция А
Время
Транзакция В
—
—
—
—
FETCH СЧЕТ 1 (40):
t1
—
(установить блокировку
типа S для СЧЕТА 1):
—
сумма = 40
—
—
—
FETCH СЧЕТ 2 (50):
t2
—
(установить блокировку
типа S для СЧЕТА 2):
—
сумма = 90
t3
FETCH СЧЕТ 3 (30)
—
(установить блокировку
—
типа S для СЧЕТА 3):
—
—
—
t4
UPDATE СЧЕТ 3
—
(установить блокировку
—
типа Х для СЧЕТА З):
—
3020
—
—
t5
FETCH СЧЕТ 1 (40) (
—
запрос блокировки)
—
типа S для СЧЕТА 1
—
ждать
—
t6
UPDATE СЧЕТ 1
—
(установить блокировку
—
типа Х для СЧЕТА 1)
FETCH СЧЕТ 3 (20):
t7
ждать
(запрос блокировки
ждать
S для СЧЕТА З):
ждать
Ждать
ждать
Ждать
Рис. 11.9. Исключается анализ на противоречивость, но в момент t6 возникает тупиковая ситуация
Рис. 11.9—это модифицированный вариант рис. 11.4, показывающий, что произошло бы при параллельном исполнении представленных на этом рисунке транзакций под управлением механизма блокирования, который используется в системе DB2. Нетрудно видеть, что запрос транзакции В на операцию UPDATE и момент t6 не принимается, поскольку он является неявным запросом на блокировку типа Х для СЧЕТА 1, а такой запрос вступает в конфликт с блокировкой типа S, уже установленной транзакцией А. Поэтому В переходит в состояние ожидания. Подобным же образом в момент t7 не принимается также запрос транзакции А на выполнение операции FETCH, так как он является неявным запросом на установление блокировки типа S для СЧЕТА 3, а такой запрос вступает в конфликт с блокировкой типа X, уже установленной транзакцией В. По этой причине А также переходит в состояние ожидания. Итак, снова первоначальная проблема (в данном случае, проблема анализа на противоречивость) решается в системе DB2 путем форсирования возникновения тупиковой ситуации. Как уже говорилось, проблема тупиковых ситуаций обсуждается в разделе 11.7.
11.6. ВОЗМОЖНОСТИ ЯВНОГО БЛОКИРОВАНИЯ
Помимо механизма неявного блокирования, описанного в предыдущем разделе, система DB2 обеспечивает некоторые явные возможности, о которых программист должен быть по меньшей мере осведомлен, хотя в большинстве ситуаций будет достаточно неявных возможностей. Средства явного блокирования в некоторой мере неоднородны и состоят из 1) предложения LOCK TABLE (блокировать таблицу) языка SQL, 2) факультативного параметра уровня изоляции в команде BIND и 3) параметра «единица блокирования» табличного пространства.
Предложение LOCK TABLE
Предложение LOCK TABLE языка SQL имеет следующий формат:
LOCK TABLE имя—таблицы IN режим MODE;
где «режим» может специфицироваться как SHARE (совместный) или EXCLUSIVE (монопольный), «имя—таблицы» должно обозначать базовую таблицу, а не представление. Например:
LOCK TABLE SP IN EXCLUSIVE MODE;
Это предложение устанавливает блокировку типа Х для всей базовой таблицы SP в интересах издающей его транзакции. Конечно, эта транзакция, возможно, должна будет ждать до тех пор, пока она сможет установить эту блокировку, если некоторая другая транзакция ранее уже установила блокировку, противоречащую данной. Как только указанная блокировка будет установлена, никакая другая транзакция не сможет обращаться каким-либо образом к любой части этой таблицы до тех пор, пока не будет снята первоначальная блокировка. Эта блокировка не будет снята, пока не завершится данная программа21 (а не транзакция).
Если вместо EXCLUSIVE специфицируется SHARE, то данная транзакция будет, конечно, устанавливать блокировку типа S, а не типа X. При этом другие транзакции не смогут установить блокировку типа Х для рассматриваемой таблицы или какой-либо се части до тех пор, пока не будет снята первоначальная блокировка. Однако до этого момента времени они смогут устанавливать блокировку типа S для данной таблицы или некоторой ее части.
Назначение предложения LOCK TABLE состоит в следующем. Если транзакция обращается к большому числу отдельных записей и поочередно блокирует их, как было описано в предыдущем разделе, то накладные расходы на блокирование для этой транзакции могут быть весьма высокими в отношении как пространства, так и времени—пространства для удержания блокировок к основной памяти, а времени — для их установки. Рассмотрим, например, программу, которая просматривает всю таблицу поставок и печатает ее. Для такой программы, вероятно, лучше установить единственную блокировку на уровне таблицы, как в приведенном выше примере, и таким образом полностью обойтись для этой таблицы без необходимости блокировок на уровне записей. Это делается, конечно, в ущерб параллелизму, однако производительность данной отдельной транзакции будет повышаться и, возможно, в такой степени, что будет также повышаться суммарная производительность системы.
Установление блокировки типа Х на уровне таблицы действительно позволит полностью обойтись без необходимости блокировок на уровне записей для рассматриваемой таблицы, как было только что сказано. Установление же блокировки типа S на уровне таблицы избавит от блокировок типа Х на уровне записей (опять-таки для рассматриваемой таблицы). В самом деле, если программа обновляет какую-либо запись в данной таблице, ей все же потребуется установить блокировку типа Х для этой конкретной записи, благодаря чему параллельные транзакции будут лишены возможности «увидеть» незафиксированное изменение.
Примечание. Хотя операция LOCK TABLE определяется, конечно, как блокирование базовой таблицы, фактически система DB2 блокирует табличное пространство, которое содержит эту таблицу (см. главу 13).
Уровень изоляции
Уровень изоляции — это свойство плана прикладной задачи. Оно специфицируется с помощью параметра команды BIND, которая продуцирует этот план. Имеются два возможных значения этого параметра: RR («повторяемое чтение») и CS («стабильноcть курсора»), причем RR—значение, которое принимается по умолчанию.
Указанные значения параметра имеют следующий смысл:
— «Стабильность курсора» означает, что если использующая этот план транзакция:
а) получает возможность доступа к некоторой конкретной записи путем установки курсора так, чтобы он указывал эту запись, и таким образом
б) устанавливает для этой записи блокировку типа S, а затем
в) отказывается от возможности доступа к этой записи, не обновляя ее, и поэтому
г) не повышает ее блокировку типа S до уровня X, то
д) можно снять эту блокировку типа S, не обязательно дожидаясь следующей точки синхронизации.
— «Повторяемое чтение» означает, что блокировки типа S на уровне записей удерживаются до следующей точки синхронизации подобно блокировкам типа X. Уровень изоляции CS может обеспечить несколько большую степень параллелизма, чем уровень изоляции RR, но вообще это не очень хороший вариант. Именно поэтому по умолчанию принимается значение RR. Проблема, связанная со значением CS, состоит в том, что для транзакции, оперирующей на этом уровне, запись может быть изменена «у нее за спиной», как показано на рис. 11.4, и поэтому такая транзакция может продуцировать неверный ответ. Фактически, если транзакция оперирует на уровне изоляции CS, то теоретически всегда возможно определить вторую транзакцию, которая может исполняться параллельно с первой таким образом, чтобы продуцировать некорректный общий результат. Напротив, транзакция, оперирующая на уровне изоляции RR, может вести себя совершенно так, как если бы она исполнялась в системе с единственным пользователем.
Заметим, что хотя уровень изоляции специфицируется как часть команды BIND, а не как часть программы, программисту все же необходимо быть о нем осведомленным, поскольку от значения этого параметра может зависеть логика программы, иначе говоря, оно может влиять на способ, которым должна кодироваться программа.
Параметр «единица блокирования» табличного пространства
Этот вопрос здесь затрагивается только для полноты рассмотрения. Следующее описание, вероятно, не будет иметь большого смысла до тех пор, пока читатель не изучит главу 13.
Как указывалось в разделе 11.5, механизм неявного блокирования в системе DB2 определяется в терминах блокировок уровня записей. Однако это логическое определение. Физически DB2 блокирует данные в терминах страниц или табличных пространств. Иначе говоря, когда заданная транзакция логически блокирует некоторую отдельную запись, система DB2 физически блокирует либо страницу, либо табличное пространство, которое содержит эту запись, в зависимости от того, что было специфицировано для этого табличного пространства в запросе, когда оно создавалось.
Для любого заданного табличного пространства может быть специфицирован в качестве «единицы блокирования» один из следующих вариантов: PAGE (страница), TABLESPACE (табличное пространство) или ANY (любой из предшествующих вариантов). При этом:
— ANY (вариант по умолчанию) означает, что DB2 сама будет решать вопрос о подходящей физической единице блокирования для табличного пространства каждого плана, т. е. для одного и того же табличного пространства один план может устанавливать блокировки на уровне страниц, в то время как другой устанавливает их на уровне табличного пространства.
— TABLESPACE означает, что все блокировки, устанавливаемые на данные в этом табличном пространстве, будут осуществляться на уровне табличного пространства.
— PAGE означает, что в заданном табличном пространстве блокировки данных будут всякий раз, когда это возможно, устанавливаться на уровне страниц. Однако иногда DB2 будет все же устанавливать блокировки на уровне табличного пространства. Детальное рассмотрение этого вопроса выходит за рамки данной работы.
11.7. ТУПИКОВАЯ СИТУАЦИЯ
Выше было показано, каким образом блокирование может использоваться для решения трех основных проблем параллельных процессов. Однако мы видели также, что, к сожалению, блокирование порождает свои собственные проблемы, прежде всего проблему тупиковых ситуаций. В разделе 11.5 были приведены два примера тупиковых ситуаций. Ниже на рис. 11.10 показан несколько более общий случай этой проблемы.
Примечание. Имеется в виду, что приведенные на этом рисунке операции блокировки обозначают любые операции, устанавливающие блокировки, а совсем не обязательно предложения SQL LOCK TABLE.
-
Транзакция А
Время
Транзакция В
—
—
—
—
LOCK R1 IN X MODE
t1
—
—
—
—
t2
LOCK R2 IN X MODE
—
—
LOCK1R2 IN X MODE
t3
—
ждать
—
ждать
t4
LOCK R1 IN X MODE
ждать
ждать
ждать
ждать
Рис. 11.10. Пример тупиковой ситуации
Тупиковая ситуация — это такая ситуация, при которой две или более транзакции одновременно находятся в состоянии ожидания, и каждая из них ожидает, пока одна из других транзакций снимет блокировку, прежде чем ее исполнение сможет продолжаться. На рис. 11.10 показана тупиковая ситуация, вовлекающая две транзакции, но возможны также, по крайней мере теоретически, тупиковые ситуации, вовлекающие три, четыре и более транзакций. На практике, однако, тупиковые ситуации почти никогда не вовлекают более двух транзакций.
Если возникает тупиковая ситуация, система обнаруживает и ликвидирует ее. Для того чтобы ликвидировать тупиковую ситуацию, одна из вовлеченных в нее транзакций выбирается в качестве жертвы и, в зависимости от обстановки, либо автоматически производится ее откат, либо от нее требуется произвести откат самостоятельно. Между прочим на этот запрос не может последовать отказа. В любом случае данная транзакция снимет свои блокировки и, таким образом, позволит продолжить исполнение некоторой другой транзакции. Следовательно, в общем случае любая операция, требующая блокировки, в частности любая операция манипулирования данными языка SQL, может быть отвергнута с отрицательным значением SQLCODE, указывающим, что эта транзакция только что была выбрана жертвой в тупиковой ситуации, и либо уже был произведен ее откат, либо требуется его выполнить. Тупиковые ситуации представляют собой, таким образом, важную проблему, когда речь идет о прикладном программисте, поскольку может потребоваться включить в прикладные программы явные средства, имеющие с ними дело, если они возникают. Например:
ЕХЕС SQL . . . ;
IF SQLCODE = значение, указывающее ”жертву тупиковой ситуации”
THEN DO;
ROLLBACK;
повторно инициализировать переменные с помощью
начальных входных данных;
GO TO начало программы;
END;
Здесь предполагается, что программа где-либо сохранила свои начальные входные параметры (не в базе данных! — почему?) для подготовки как раз к таким возможным случаям.
11.8. РЕЗЮМЕ
В этой довольно длинной главе вопрос об управлении транзакциями был рассмотрен как в общем виде, так и конкретно в рамках системы DB2. Транзакция является не только логической единицей работы, но и единицей восстановления, а также, как можно было убедиться в двух последних разделах, единицей параллелизма. Управление транзакциями—это задача диспетчеризации исполнения транзакций таким образом, чтобы каждая транзакция могла рассматриваться как высказывание типа «все или ничего» даже при условии, что возможны произвольные сбои на части любой отдельной транзакции или самой системы, и при условии, что множество независимых транзакций может исполняться параллельно и обращаться к одним и тем же данным. Фактически общую функцию системы вполне можно было бы определить как надежное исполнение транзакций.
В системе DB2, в частности, транзакции ограничиваются точками синхронизации, которые учреждаются при инициации программ, выполнении операций COMMIT (успешное завершение) и ROLLBACK (неудачное завершение).
Примечание. COMMIT и ROLLBACK—это операции, которые используются в обстановке TSO. В обстановке IMS и CICS используются другие, аналогичные операции. Система DB2 гарантирует атомарность таких транзакций, как показано в разделах 11.2 и 11.3.
Управление параллельным исполнением транзакций в DB2 основано на блокировании. По существу, каждая запись, к которой обращается транзакция, подвергается блокировке типа S. Если транзакция собирается обновлять запись, то эта блокировка типа S повышается до уровня блокировки типа X. Блокировки типа X, и обычно также типа S, удерживаются до следующей точки синхронизации. Этот простой протокол решает три основные проблемы управления параллельными транзакциями, но вместе с тем порождает возможность тупиковых ситуаций. Следовательно, прикладные программы должны быть готовы иметь дело с такой возможностью. О возникновении тупиковой ситуации сигнализирует некоторое отрицательное значение SQLCODE, которое потенциально может возвращаться после любой операции языка SQL, требующей блокировки.
УПРАЖНЕНИЯ
11.1 Следующий список представляет последовательность событий при параллельном исполнении множества транзакций T1, T2, . . ., Т12 системы DB2, каждая из которых действует на уровне изоляции RR. При этом А, В, . . ., Н, ... являются записями, а не курсорами.
Момент t0 . . . . . .
Момент t1 (T1) : FETCH A
Момент t2 (T2) : FETCH В
— (T1) : FETCH С
— (Т4) : FETCH D
— (Т5) : FETCH A
— (T2) : FETCH E
— (T2) : UPDATE E
— (ТЗ) : FETCH F
— (T2) : FETCH F
— (Т5) : UPDATE A
— (T1) : COMMIT
— (Т6) : FETCH A
— (Т5) : ROLLBACK
— (Т6) : FETCH С
— (Т6) : UPDATE С
— (Т7) : FETCH G
— (Т8) : FETCH H
— (Т9) : FETCH G
— (Т9) : UPDATE G
— (Т8) : FETCH E
— (Т7) : COMMIT
— (Т9) : FETCH H
— (ТЗ) : FETCH G
— (Т10) : FETCH A
— (Т9) : UPDATE H
— (Т6) : COMMIT
— (Т11) : FETCH С
— (Т12) : FETCH D
— (Т12) : FETCH С
— (Т2) : UPDATE F
— (Т11) : UPDATE С
— (Т12) : FETCH A
— (Т10) : UPDATE A
— (Т12) : UPDATE D
— (Т4) : FETCH G
Момент tn . . . . . .
Имеются ли какие-либо тупиковые ситуации в момент tn?
ОТВЕТЫ К НЕКОТОРЫМ УПРАЖНЕНИЯМ
11.1. В момент tn никакие транзакции вообще не выполняют какой-либо полезной работы! Имеется одна тупиковая ситуация, вовлекающая транзакции Т2, ТЗ, Т9 и Т8. Кроме того, Т4 ожидает Т9, Т12 ожидает Т4, а Т10 и Т11 ожидают Т12. Эту ситуацию можно представить с помощью графа (графа ожидания — рис. 11.11), в котором узлы представляют транзакции, а направленное ребро исходящее из узла Ti в узел Tj, указывает, что Ti ожидает Tj. Ребра графа помечены именами записей и уровнями блокировки, которых эти транзакции ожидают.
![](images/205054-nomer-3b927178.gif)
Рис. 11.11. Граф ожидания