Транзакция — группа последовательных операций с базой данных, которая представляет собой логическую единицу работы с данными, такая, что:
1) либо результаты всех операторов, входящих в транзакцию, отображаются в БД;
2) либо воздействие всех операторов полностью отсутствует.
При этом для поддержания ограничений целостности на уровне БД допускается их нарушение внутри транзакции так, чтобы к моменту завершения транзакции условия целостности были соблюдены.
Для обеспечения контроля целостности каждая транзакция должна начинаться при целостном состоянии БД и должна сохранить это состояние целостным после своего завершения. Если операторы, объединенные в транзакцию, выполняются, то происходит нормальное завершение транзакции, и БД переходит в обновленное (целостное) состояние. Если же происходит сбой при выполнении транзакции, то происходит так называемый откат к исходному состоянию БД.
Метод сериализации транзакций – это механизм их выполнения по такому плану, когда результат совместного выполнения транзакций эквивалентен результату некоторого последовательного выполнения этих же транзакций. Обеспечение такого механизма является основной функцией управления транзакциями. Система, в которой поддерживается метод сериализации транзакций, реально обеспечивает изолированность пользователя при работе с БД.
|
|
На самом деле между транзакциями могут существовать следующие виды конфликтов:
• Транзакция 2 пытается изменять объект, измененный незакончившейся транзакцией 1 (W-W – конфликт)
• Транзакция 2 пытается изменять объект, прочитанный незакончившейся транзакцией 1 (R-W – конфликт)
• Транзакция 2 пытается читать объект, измененный незакончившейся транзакцией 1 (W-R – конфликт)
Практически все методы сериализации транзакций основываются на учете этих конфликтов.
Захват и освобождение объекта. Для обеспечения сериализации транзакций применяются методы «захвата» и «освобождения» объектов, производимого по инициативе транзакции: транзакция «захватывает» объект, что приводит к его блокировке для других транзакций, и освобождает его только при своем завершении. При этом захваты объектов несколькими транзакциями на чтение совместимы (т.е. нескольким транзакциям разрешается читать один и тот же объект), захват объекта на чтение одной транзакцией не совместим с захватом другой транзакцией того же объекта на запись, и захваты одного объекта разными транзакциями на запись не совместимы. Тем самым, выделяются два основных режима захватов:
• Совместный режим – S (Shared), означающий разделяемый захват объекта и необходимый для выполнения операции чтения объекта
|
|
• Монпольный режим – X (eXclusive), означающий монопольный захват объекта и необходимый для выполнения операций записи, удаления и модификации.
Наиболее распространенный в СУБД, основанных на архитектуре «клиент – сервер», является подход, реализующий соблюдение двухфазного протокола захватов объектов БД. В общих чертах протокол состоит в том, что перед выполнением любой операции над объектом базы данных от имени транзакции запрашивается захват объекта в соответствующем режиме (в зависимости от вида операции – совместнм или монопольном). В соответствии с этим протоколом выполнение транзакции разбивается на две фазы: первая фаза транзакции – накопление захватов; вторая фаза (фиксация или откат) – освобождение захватов.
При соблюдении двухфазного протокола основная проблема состоит в том, что следует считать объектом для захвата?
В контексте реляционных баз данных возможны следующие варианты:
• Файл – физический (с точки зрения базы данных) объект, область хранения нескольких отношений и, возможно, индексов
• Таблица – логический объект, соответствующий множеству записей данного отношения
• Страница данных – физический объект, хранящий записи одного или нескольких отношений, индексную или служебную информацию
• Запись – элементарный физический объект базы данных
Очевидно, что чем крупнее объект захвата, тем меньше захватов будет поддерживаться в системе, и на это, соответственно, будут тратиться меньшие накладные расходы. Более того, если выбрать в качестве уровня объектов для захватов файл или отношение, то будет решена даже проблема строк-призраков. Однако при использовании для захватов крупных объектов возрастает вероятность конфликтов транзакций и тем самым уменьшается допускаемая степень их параллельного выполнения. Фактически, при укрупнении объекта синхронизированного захвата мы умышленно огрубляем ситуацию и видим конфликты в тех ситуациях, когда на самом деле конфликтов нет.
Метод временных меток. Альтернативный метод сериализации транзакций, хорошо работающий в условиях редких конфликтов транзакций и не требующий построения графа ожидания транзакций. основан на использовании временных меток.
Основная идея метода (у которого существует множество разновидностей) состоит в следующем: если транзакция T1 началась раньше транзакции T2, то система обеспечивает такой режим выполнения, как если бы T1 была целиком выполнена до начала T2.
Для этого каждой транзакции T предписывается временная метка t, соответствующая времени начала T. При выполнении операции над объектом r транзакция T помечает его своей временной меткой и типом операции (чтение или изменение).
Перед выполнением операции над объектом r транзакция T1 выполняет следующие действия:
• Проверяет, не закончилась ли транзакция T, пометившая этот объект. Если T закончилась, T1 помечает объект r и выполняет свою операцию.
• Если транзакция T не завершилась, то T1 проверяет конфликтность операций. Если операции неконфликтны, при объекте r остается или проставляется временная метка с меньшим значением, и транзакция T1 выполняет свою операцию.
• Если операции T1 и T конфликтуют, то если t(T) > t(T1) (т.е. транзакция T является более "молодой", чем T), производится откат T и T1 продолжает работу.
• Если же t(T) < t(T1) (T "старше" T1), то T1 получает новую временную метку и начинается заново.
К недостаткам метода временных меток относятся потенциально более частые откаты транзакций, чем в случае использования синхронизационных захватов. Это связано с тем, что конфликтность транзакций определяется более грубо. Кроме того, в распределенных системах не очень просто вырабатывать глобальные временные метки с отношением полного порядка (это отдельная большая наука).
Но в распределенных системах эти недостатки окупаются тем, что не нужно распознавать тупики, а как мы уже отмечали, построение графа ожидания в распределенных системах стоит очень дорого.