Технологии распределенных баз данных
I. Обработка и оптимизация запросов
Обработка запроса - это процесс трансляции декларативного определения запроса в операции манипулирования данными низкого уровня.
Оптимизация запроса - это процедура выбора "наилучшей" стратегии для реализации запроса из множества альтернатив.
Для централизованной СУБД весь процесс состоит обычно из двух шагов:
(1) Декомпозиция запроса - это трансляция его с языка SQL в выражение реляционной алгебры. В ходе декомпозиции запрос подвергается семантическому анализу; при этом некорректные запросы отвергаются, а корректные упрощаются. Упрощение заключается, в частности, в исключении избыточных предикатов, которые могли быть привнесены за счет использования представлений, а также исходя из требований безопасности и семантической целостности. Упрощенный запрос преобразуется в алгебраическую форму.
Примеры анализа предикатов:
where position="manager" and position="assistant" - предикат противоречив;
where (position="manager" and position="assistant") or salary >2000 может быть заменен на предикат where salary>2000, т.к. противоречивую фразу можно заменить на False.
(2) Для заданного SQL-запроса существует более чем одно алгебраическое представление, причем некоторые из них могут быть "лучше" других. "Качество" алгебраического выражения определяется исходя из объема затрат, необходимых для его вычисления. Традиционная процедура состоит в том, чтобы сначала оттранслировать SQL-запрос в какое-нибудь выражение, а затем, применяя правила эквивалентных алгебраических преобразований, получать из него другие алгебраические преобразования, пока не будет найдено "наилучшее". При поиске "наилучшего" выражения используется функция стоимости, в соответствии с которой вычисляется сумма затрат, необходимых для выполнения запроса.
В распределенной СУБД между шагами декомпозиции и оптимизации запроса включаются еще два действия:
(1+) Исходной информацией для локализации данных служит алгебраическое выражение, полученное на этапе декомпозиции запроса. В этом выражении фигурируют глобальные отношения без учета их фрагментации или распределения. Сущность данного шага заключается в том, чтобы локализовать участвующие в запросе данные, используя информацию об их распределении. При этом выявляются фрагменты, реально участвующие в запросе, а запрос преобразуется к форме, где операции применяются уже не к глобальным отношениям, а к фрагментам. Ранее отмечалось, что правила фрагментации выражаются посредством реляционных операций:
Распределенные отношения реконструируются путем применения инверсии правил фрагментации. Это называется программой локализации. Программа локализации для
(2-) Исходной информацией для третьего шага является фрагментный запрос, т. е. алгебраическое выражение над фрагментами. Цель глобальной оптимизации - найти стратегию выполнения запроса, близкую к оптимальной (вычислительно трудноразрешимая задача). Стратегия выполнения распределенного запроса выражается в терминах операций реляционной алгебры и коммуникационных примитивов (операций "послать"/"получить"), описывающих пересылки данных между узлами. Ранее (1) запрос уже был в определенной мере оптимизирован, в частности, за счет удаления избыточных выражений. Однако проведенные оптимизации не зависели от характеристик фрагментов, например их мощности и не были учитывали коммуникационных операций. Путем перестановок операций в рамках фрагментного запроса можно получить множество эквивалентных планов его выполнения, среди которых ищется "наилучший".
Оптимизатор запросов обычно представляется в виде трех компонентов: пространство поиска (1), модель стоимости (2) и стратегия поиска (3).
Пространство поиска (1) - это множество альтернативных планов выполнения исходного запроса. Планы эквивалентны в том смысле, что они дают один и тот же результат, но различаются порядком и способами выполнения отдельных операций.
Модель стоимости (2) - это способ оценить стоимость реализации заданного плана. Для того чтобы оценка была близка к реальности, модель стоимости должна учитывать свойства среды параллельных вычислений.
Стратегия поиска - это способ обхода пространства поиска и выбора наилучшего плана. Она определяет, какие планы и в каком порядке следует выбирать и оценивать.
В распределенной среде функции стоимости определяется в единицах времени и оценивает затраты таких ресурсов, как
Иногда в распределенных СУБД применяется упрощенный подход, когда в качестве наиболее значимых рассматриваются лишь коммуникационные затраты. Это справедливо для глобальных сетей, где из-за ограниченной пропускной способности линий связи пересылки данных обходятся значительно дороже, чем при локальной обработке.
Важнейший аспект оптимизации запросов - это порядок выполнения соединений (самая дорогостоящая операция), поскольку его изменение может привести к ускорению до нескольких порядков. Базовая методика для оптимизации последовательности соединений заключается в применении оператора полусоединений (semijoin).
Операция полусоединения отношений R и S определяет отношение, которое содержит кортежи отношения R, которые входят в соединение отношений R и S.
II. Управление одновременным доступом
Проблема эта уже нами рассматривалась ранее: для поддержания согласованного состояния данных необходимо обеспечить синхронизацию доступа. Синхронизация достигается путем применения алгоритмов управления одновременным доступом
Алгоритмы управления одновременным доступом обеспечивают:
Наиболее популярные алгоритмы управления одновременным доступом основаны на механизме блокировок. В такой схеме всякий раз, когда транзакция пытается получить доступ к какой-либо единице памяти (как правило, странице), на эту единицу накладывается блокировка в одном из режимов - разделяемом или исключительном. Блокировки накладываются в соответствии с правилами совместимости блокировок, исключающими конфликты чтение-запись, запись-чтение и запись-запись. Существует теорема, что сериализуемость транзакций заведомо гарантируется, если блокировки, относящиеся к одновременно выполняемым транзакциям, удовлетворяют правилу: "Ни одна блокировка от имени какой-либо транзакции не должна устанавливаться, пока не будет снята ранее установленная блокировка". Это правило известно под названием двухфазового блокирования (транзакция сначала устанавливает блокировки, а потом блокировки снимает).
Для распределенных СУБД те же задачи переносятся на распределенную среду: транзакции могут выполняться на нескольких узлах, где располагаются необходимые данные. Выполнение множества распределенных транзакций сериализуемо (свойство глобальной сериализуемостью) тогда и только тогда, когда:
В алгоритмах, основанных на блокировании, для обеспечения свойства глобальной сериализуемости применяется один из трех протоколов:
При централизованном блокировании для всей распределенной базы данных поддерживается единая таблица блокировок. Эта таблица, располагаемая на одном из узлов, находится под управлением единого менеджера блокировок. Менеджер блокировок отвечает за установку и снятие блокировок от имени всех транзакций. Поскольку управление блокировками сосредоточено на одном узле, то оно аналогично централизованному управлению одновременным доступом, и глобальная сериализуемость обеспечивается достаточно легко. Общая схема:
С алгоритмом связаны две проблемы. Во-первых, центральный узел может стать узким местом как из-за большого объема обработки данных, так и из-за генерируемого вокруг него интенсивного сетевого трафика (1). Во-вторых, надежность такой системы ограничена, поскольку отказ или недоступность центрального узла приводит к выходу из строя всей системы (2).
Блокирование первичной копии - это алгоритм управления одновременным доступом, применяемый для баз данных с репликациями, где копии одних и тех же данных могут храниться на множестве узлов. Одна из таких копий выделяется как первичная, и для доступа к любому элементу данных необходимо установить блокировку на его первичную копию. Множество первичных копий элементов данных известно всем узлам распределенной системы, и запросы транзакций на блокирование направляются узлам, где хранятся первичные копии (а данные могут быть из другого места). При обновлении элемента данных достаточно установить блокировку для записи только его первичной копии. После того как первичная копия будет обновлена, внесенные изменения могут быть распространены на все ведомые копии (желательно с максимальной скоростью). Алгоритм хорош для нечастых обновлений данных. Если в распределенной базе данных репликации не используются, то данный алгоритм сводится к алгоритму распределенного блокирования.
Алгоритм распределенного (или децентрализованного) блокирования предполагает распределение обязанностей по управлению блокировками между всеми узлами системы. Для выполнения транзакции необходимо участие и взаимная координация менеджеров блокировок на нескольких узлах. Каждый отвечает за свой узел. Блокировки устанавливаются на всех узлах, данные которых участвуют в транзакции. Для операции считывания используется любая копия, при выполнении операции обновления блокируются все копии, где содержится блокируемый элемент.
Алгоритмам распределенного блокирования не свойственны недостатки механизма централизованного блокирования, связанные с перегруженностью центрального узла. Однако алгоритмы этого типа сложнее, а коммуникационные затраты, необходимые для установки всех требуемых блокировок, выше.
В протоколе блокирования большинства когда транзакции требуется считать или записать элемент данных, реплики которого имеются в n узлах, оно должна отправить запрос на блокирование этого элемента на более половину узлов, где содержится его копия. Транзакция не продолжается, пока не установлены блокировки. Если это не сделано за определенный промежуток времени, транзакция отменяет запросы и информирует все узлы. Если большинство достигнуто, об этом информируются все узлы и устанавливается либо разделяемая блокировка для чтения либо монопольная блокировка для записи (среднее положение между двумя предыдущими протоколами).
Общий побочный эффект всех алгоритмов управления одновременным доступом посредством блокирования - возможность тупиковых ситуаций. Задача обнаружения и преодоления тупиков особенно сложна в распределенных системах. Тем не менее, благодаря относительной простоте и эффективности алгоритмов блокирования, они имеют значительно большую популярность, чем альтернативные
Алгоритмы, основанные на временных метках, выполняют конфликтующие операции транзакций в соответствии с временными метками, присвоенными транзакциям при их регистрации.
Алгоритмы оптимистичного управления исходят из предположения о том, что конфликты между транзакциями редки, и доводят транзакцию до конца, а затем производят проверку корректности. Если выясняется, что фиксация данной транзакции повлечет нарушение сериализуемости, то транзакция откатывается и запускается снова.
Три метода выделения взаимных блокировок в распределенной среде:
При центализованном выявлении взаимных блокировок один из узлов назначается координатором взаимных блокировок (Deadlock Detection Coordinator, DDC) и каждый менеджер блокировок с определенным интервалом направляет DDC свой локальный граф ожидания. DDC строит глобальный граф ожидания и анализирует его. Находя циклы, DDC разрушает их, выбрав транзакцию, которая должна быть отменена.
Недостаток: узел с DDC является узким местом (перегрузка его, проблемы в случае его отказа).
При иерархическом методе выявлении взаимных блокировок узлы в сети образуют некоторую иерархию, и каждый из узлов посылает для анализа свой локальный граф ожидания узлу, стоящему выше в иерархии. DDC, расположенный в вышестоящем узле, строит и анализирует глобальный граф ожидания на основании информации, полученной с нижестоящих узлов.
В распределенном методе к локальному графу ожидания добавляется внешний узел T(ext), отражающий наличие агента на удаленном узле. Когда транзакция T1 в узле S1 создает агента в узле S2, к локальному графу добавляется ребро, соединяющее T1 и T(ext) и помеченное именем узла S2. Если в этом узле (S2) запущена транзакция, создавшая агента в узле S3, то узел T(ext) соединяется ребром с транзакцией, запущенной в этом узле S3.
Наличие циклов в графе ожидания, не включающих T(ext), свидетельствует о существовании локальной взаимной блокировки.
Наличие циклов в графе ожидания, включающих T(ext), свидетельствует о возможности существования глобальной взаимной блокировки.
Для уточнения этого узел, первый обнаруживший вероятность существования глобальной взаимной блокировки (например, S1), посылает свой локальный граф ожиданий в узел (S1), где в состоянии ожидания находится транзакция T1, созданная в этом узле. Там графы сливаются, анализируются и, если подозрения остаются, слитый граф пересылается далее, пока возможность существования глобальной взаимной блокировки не будет установлена или опровергнута.
III. Целостность данных и протоколы обеспечения надежности
Ранее отмечалось, что распределенные СУБД потенциально более надежны в силу того, что системные компоненты в них дублируются, и тем самым исключаются одиночные точки отказа. Однако это входит в противоречие с проблемой целостности данных, для решения которой необходимо синхронное и согласованное изменение данных в нескольких локальных базах данных, составляющих DDB.
В распределенной СУБД различаются четыре типа сбоев:
Причин сбоев транзакции может быть несколько:
Обычный способ обработки таких сбоев заключается в том, чтобы прервать транзакцию и откатить базу данных к состоянию, предшествовавшему началу транзакции.
Cбои узлов (системные сбои) могут быть вызваны
Следствие системных сбоев - потеря содержимого оперативной памяти, в частности буферов оперативной памяти (часть базы данных, хранимая в буферах, называется неустойчивой базой данных). В то же время данные, находящиеся во внешней памяти, остаются в сохранности (часть базы, называемая стабильной базой данных). Обычное средство борьбы против системных сбоев - использование протоколов журнализации, например журнализация с упреждающей записью, которые создают в системных журналах записи обо всех изменениях в базе данных и в подходящие моменты времени переносят журнальные записи, а также страницы неустойчивой базы данных во внешнюю память. В распределенной базе данных проблема системных сбоев выражается еще и в том, что отказавший узел не может участвовать в транзакциях.
Сбои носителей связаны с отказами устройств внешней памяти, на которых хранится стабильная база данных. Обычно эта проблема решается путем применения дуплексных устройств и поддержания архивных копий базы данных.
Рассмотренные выше три типа сбоев характерны и для централизованных, и для распределенных СУБД. Коммуникационные сбои, напротив, являются специфической проблемой распределенных баз данных. Они подразделяются на несколько разновидностей, наиболее распространенные из которых -
Первые из двух типов сбоев находятся в компетенции сетевых протоколов, два последних лежат в ведении СУБД и должны учитываться в протоколах обеспечения надежности.
Если один узел ожидает сообщения от другого, а оно не поступает, то причин тому может быть несколько:
В любом случае ожидающий узел по истечении определенного промежутка времени просто решает, что узел-партнер стал недоступен. Последствием повреждений на линиях связи может стать фрагментация сети, когда множество узлов распадается на группы, внутри которых имеется связь, а коммуникации между группами невозможны.
Протоколы обеспечения надежности поддерживают два свойства транзакций: атомарность и долговечность. Атомарность означает, что выполняются либо все действия транзакции, либо не выполняется ни одно (принцип "все или ничего"). Атомарность гарантируется даже в условиях возможных отказов. Долговечность означает, что результат успешно завершенной (зафиксированной) транзакции сохраняется даже при последующих сбоях.
Для обеспечения атомарности и долговечности необходимы
Если DDB однородна - то есть на всех узлах данные хранятся в формате одной базы и на всех узлах функционирует одна и та же СУБД, то в качестве протокола атомарной фиксации является протокол двухфазовой фиксации транзакций (2PC - 2 Phase Commit).
Три основных принципа лежат в ее основе:
1 фаза 2PC - подготовка к фиксации транзакции (голосование).
2 фаза 2PC- глобальные фиксация или откат транзакции (принятие решения).
В простейшем варианте работа 2PC состоит из трех шагов и выглядит следующим образом:
Заметим, что участникам, проголосовавшим за прерывание, сообщение посылать не нужно, поскольку они сами способны принять решение исходя из правил 2PC. Эта ситуация известна под названием опции одностороннего прерывания.
Если время ожидания исчерпано, то ждущий процесс (координатор или участник) следует протоколу терминирования (протокол терминирования - протокол, при помощи которого отдельный узел может принять решение о том, как следует завершить транзакцию в условиях, когда он не может взаимодействовать с другими участвующими в данной транзакции узлами).
Логика протокола терминирования может быть следующей:
Предположим, что участник, уже отославший свой голос за фиксацию транзакции, не дождался в течение заданного времени сообщения от координатора об окончательном решении. В этом случае участник находится в состоянии готовности. Раз он находится в состоянии готовности, то это означает, что ранее он проголосовал за фиксацию и теперь не имеет права изменить свое решение и прервать транзакцию. Принять одностороннее решение о фиксации транзакции он также не может, поскольку кто-то из участников, возможно, проголосовал против. В такой ситуации участник вынужден оставаться в заблокированном состоянии, пока не узнает от кого-нибудь еще (координатора или других участников) о судьбе данной транзакции. В условиях, когда участники не могут взаимодействовать друг с другом, узел должен ждать сообщения от координатора. Поскольку координатор отказал, участник остается заблокированным. Разумного протокола терминирования в такой модели предложить нельзя.
Если участники способны взаимодействовать друг с другом, то можно сконструировать распределенный протокол терминирования. Участник, который не дождался сообщения от координатора, может просто обратиться за помощью в принятии решения к другим участникам. Если в ходе выполнения терминирующего протокола все участники придут к выводу, что отказал только координатор, то они могут избрать в качестве координатора другой узел, где будет перезапущен процесс фиксации. Однако если отказ произошел не только на координаторе, но и на участнике, то возможна ситуация, когда участник уже успел получить от координатора окончательное решение и завершил транзакцию соответствующим образом. Это решение еще не известно другим участникам, и, если они изберут другого координатора, то есть опасность, что они завершат транзакцию не так, как это сделал отказавший участник. Приведенные примеры иллюстрируют блокирующий характер 2PC.
Предпринимались попытки создания неблокирующих протоколов (пример - протокол трехфазовой фиксации - 3PC), но высокие накладные расходы, связанные с их выполнением, препятствовали их принятию (к тому же он тоже не без изъянов). 3PC является неблокирующим протоколом, но лишь при следующих условиях:
Идея протокола 3PC состоит в устранении неопределенности периода ожидания, в который попадают участники после подтверждения своего согласия на фиксацию транзакции и до получения от координатора сообщения о глобальной фиксации или глобальном откате транзакции. В 3PC вводится 3 фаза - предфиксация между первыми двумя. После получения результатов голосования от всех участников координатор рассылает глобальное сообщение PRE-COMMIT. Участник, получивший сообщение о префиксации, знает, что все остальные участники проголосовали за фиксацию транзакции (все участники т.о. получают информацию о других). Каждый участник сообщает координатору о получении сообщения PRE-COMMIT, после чего координатор рассылает команду зафиксировать транзакцию.
Обратной стороной терминирования является восстановление. Какие действия должен предпринять восстанавливающийся после сбоя узел-координатор, чтобы привести базу данных в корректное состояние? Возможны следующие случаи.
В случае же неоднородности DDB для обеспечения согласованных изменений в нескольких базах данных используют менеджеры распределенных транзакций, относящиеся к категории middlware и реализующие модель распределенной обработки транзакций X/Open (раздел Middleware).
IY. Технология тиражирования данных
Основной недостаток физического распределения данных - жесткие требования к скорости и надежности каналов связи. Если БД распределена по нескольким территориально удаленным узлам, объединенным медленными и ненадежными каналами связи, а число одновременно работающих пользователей составляет десятки и выше, то вероятность того, что распределенная транзакция будет зафиксирована в обозримом временном интервале, становится чрезвычайно малой. В таких условиях (характерных, кстати, для большинства отечественных организаций) обработка распределенных данных практически невозможна. В действительности далеко не во всех задачах требуется обеспечение идентичности БД на различных узлах в любое время. Достаточно поддерживать тождественность данных лишь в определенные критичные моменты времени. Следовательно, можно накапливать изменения в данных в виде транзакций в одном узле и периодически копировать эти изменения на другие узлы.
Тиражирование данных (Data Replication - DR) - это асинхронный перенос изменений объектов исходной базы данных (source database) в БД, принадлежащим различным узлам распределенной системы. Функции DR выполняет специальный модуль СУБД - сервер тиражирования данных, называемый репликатором (replicator). Его задача - поддержка идентичности данных в принимающих базах данных (target database) данным в исходной БД. Сигналом для запуска репликатора служит срабатывание некоторого правила.
Принципиальная характеристика тиражирования данных заключается в отказе от физического распределения данных. Суть DR состоит в том, что любая база данных (как для СУБД, так и для работающих с ней пользователей) всегда является локальной; данные размещаются локально на том узле сети, где они обрабатываются; все транзакции в системе завершаются локально.
Реализация технологии DR отвечает на 4 вопроса:
1. Что тиражировать?
Основное понятие - понятие согласованного распределенного набора данных (consistent distributed data set - CDDS). Это набор данных, идентичность которого поддерживается репликатором во всех узлах, вовлеченных в процесс тиражирования.
CDDS может представлять собой
Строгое определение CDDS состоит в выполнении следующих условий:
Замечание. Идентичность понимается как одинаковость определения и состава данных.
И последнее положение. Ни один узел - хранитель своей части CDDS - ни чем не отличается от других, если не оговорено обратное. Все узлы равноправны и могут быть источниками и приемниками изменений. При необходимости внутри CDDS определяется приоритет данных каждого узла, используемый при автоматическом разрешении конфликтов.
2. Где тиражировать?
Следующий элемент схемы тиражирования - путь переноса изменений (data propagation path - DPP) из каждой тиражируемой базы в другие БД.
Основные схемы тиражирования:
Механизмы, регулирующие взаимоотношения между узлами (с точки зрения принимающего узла):
3. Когда тиражировать?
Элементарным изменением, вызывающим реакцию репликатора, является транзакция. Стремясь быть максимально гибким, репликатор предоставляет следующие основные возможности:
4. Как разрешать конфликты?
Репликатор самостоятельно обнаруживает конфликты (например, встречное тиражирование) и предоставляет разрешение конфликта либо администратору, либо делает это автоматически. Некоторые варианты:
Решение вышеперечисленных вопросов выливается в тот или иной протокол тиражирования.
Наиболее известным теоретическим критерием согласованности является критерий полной эквивалентности копий, который требует, чтобы по завершении транзакции все копии логического элемента данных были идентичны.
Задача протокола тиражирования - отобразить эти операции доступа к некоторому элементу х на множества операций над физическими копиями x (x1 , x2 ,..., xn). Типичный протокол тиражирования, обеспечивающий сериализуемость по критерию полной эквивалентности копий, известен под названием ROWA (Read-Once/Write-All - одно чтение, запись во все копии). Протокол ROWA отображает чтение x Read(x) на операцию чтения какой-либо из копий x Read(xi). Из какой именно копии будет производиться чтение, неважно - этот вопрос может решаться из соображений эффективности. Каждая операция записи в логический элемент данных x отображается на множество операций записи во все физические копии x.
Протокол ROWA прост и прямолинеен (достоинство), но он требует доступности всех копий элемента данных, для того чтобы транзакция была завершена (недостатки). Сбой на одном из узлов приведет к блокированию транзакции, что снижает доступность базы данных.
Ряд альтернативных алгоритмов ослабляют требование протокола ROWA. Это такие алгоритмы:
Алгоритм консенсуса большинства каждой копии данных приписывается равный по весу голос, и транзакция, изменяющая логический элемент данных, может успешно завершиться, если она наберет большинство голосов.
Алгоритм голосования на базе кворума присваивает копиям данных (возможно, неодинаковые по весу) голоса. Каждая операция доступа должна в этом случае набрать необходимый кворум, соответственно, чтения (Vr) или записи (Vw)..
Специфика механизмов DR зависит от используемой СУБД.