Отличие промышленных систем от игрушечных
Методика обеспечения целостности распределенной БД - лишь один из аспектов, определяющих упомянутое различие. Если попробовать сформулировать основной его критерий в общем виде, то, пожалуй, можно предложить следующую формулировку: в промышленной системе всегда можно дать однозначный ответ на вопрос "А что будет, если..?". Другими словами, промышленная система должна обеспечивать своими внутренними средствами предсказуемость своего состояния независимо от внешних условий. Безусловно, любое общее определение страдает неполнотой (в самом деле, формально наиболее предсказуемым является состояние системы, которая вообще никогда не работает), однако, по мнению автора, оно все-таки дает идею, необходимую для понимания сути утверждения о том, что Oracle предоставляет технологию для создания именно промышленных систем.
В качестве поясняющего примера вернемся к проблеме синхронизации тиражируемых данных. Рассмотрим вопрос об организации связи между серверами в распределенной БД. Очень соблазнительной является идея: если уж мы не требуем, чтобы целостность данных (в частности соответствие тиражированных копий друг другу) обеспечивалась в любой момент времени, нельзя ли организовать указанную связь на основе электронной почты? На первый взгляд, ничего опасного в этом нет, но вспомним, что электронная почта не гарантирует, что "письма" будут получены адресатом в той же последовательности, в которой они были посланы и даже что все они вообще будут получены. Даже если с помощью специального контроля на приеме последствия данной неоднозначности сводятся к минимуму, все равно оказывается невозможным предсказать, скажем, момент времени, когда информация об изменении одной из копий объекта дойдет до других его копий, и в каком состоянии к этому моменту эта изменившаяся копия будет находиться. Означает ли это, что электронной почтой в распределенной БД пользоваться вообще нельзя? И да, и нет. Все зависит от требований к системе. Если "свежесть" тиражированных данных требуется, допустим, в пределах суток, а последствия непредсказуемости системы и потери ее целостности не слишком разрушительны, то почему бы и нет? Но если все-таки требуется действительно промышленная система, то необходимо очень тщательно оценить все возможные последствия применения выбранного механизма взаимодействия и ввести в использование того же тиражирования такие ограничения, которые обеспечили бы требуемый уровень целостности системы.
Если вернуться к теме целостности распределенной БД с тиражируемыми данными, то при ее проектировании необходимо, как минимум, задать себе следующие вопросы.
Допустимо ли временное рассогласование тиражированных данных?
Если да, то в каких временных пределах должна осуществляться процедура их согласования, и каким образом она должна инициироваться?
Не могут ли привести сбои каких-либо элементов системы к безвозвратной потере целостности распределенной БД, всегда ли система будет корректно (и предсказуемо) вести себя в случае тех или иных сбоев?
Какова должна быть дисциплина работы с тиражированными данными, чтобы исключить возможность конфликтов между модификацией различных копий одних и тех же данных, или - если такие конфликты допускать - какова должна быть процедура их разрешения (в какой степени система будет способна делать это автоматически, и будет ли она извещать о возникновении конфликтов администратора)?
Варианты тиражирования данных в Oracle
Самым простым (и исторически реализованным первым) вариантом тиражирования в Oracle является механизм так называемых неизменяемых снимков (read-only snapshots). Он подразумевает создание удаленной копии таблицы (или ее подмножества), которая доступна только на чтение и обновляется по заданному сценарию и расписанию. Точнее, снимок определяется так же, как представление - view, т. е. он может быть основан и на нескольких таблицах.
Следующим по своей логической сложности вариантом является организация изменяемых снимков, предоставляющая возможность модификации удаленных копий. Однако, как и в предыдущем случае, отношения серверов при этом асимметричны (один из них является владельцем "оригинала" данных, хотя и подверженного удаленным изменениям).
Последним "атомарным" вариантом тиражирования в Oracle (ибо возможны также любые комбинации) является тиражирование с множественными хозяевами (multi-master site replication). При данном варианте полностью тиражируются целые наборы объектов БД (в них помимо таблиц могут входить индексы, представления, триггеры, пакеты хранимых процедур, синонимы, генераторы последовательностей). При этом тиражируются все определения и атрибуты объектов, так что в результате все хозяева их копий становятся равноправными. Любые изменения тиражированных данных непосредственно передаются ("распространяются") всем хозяевам (в отличие от варианта изменяемых снимков, где несколько снимков одного объекта могут обменяться изменениями только через посредство хозяина этого объекта). Такое решение, в частности, приводит к тому, что в системе не будет ни одного сервера, единичный выход из строя которого означал бы невозможность продолжения работы с набором тиражированных объектов.
Механизм распространения изменений в Oracle встроен в ядро системы и не требует использования никаких дополнительных программных продуктов. Любое изменение тиражированного объекта приводит в действие специальный триггер, который формирует вызов удаленной процедуры, необходимый для воспроизведения изменения во всех оставшихся копиях объекта. Далее в случае использования синхронного тиражирования сформированный вызов немедленно начинает выполняться, в случае же асинхронного тиражирования он помещается в специальную очередь отложенных вызовов, ожидая наступления момента своей передачи.
Очередь отложенных вызовов является объектом БД, а стало быть, ею можно управлять наряду с прочими объектами, после сбоев сервера она восстанавливается также вместе с другими.
Без дисциплины работать трудно
Теперь, когда общий механизм тиражирования ясен, попробуем разобраться в некоторых аспектах его применения.
Как уже упоминалось, возможны два режима тиражирования: синхронный, когда все изменения данных распространяются немедленно, и асинхронный, когда по отношению к этим изменениям применяется алгоритм "запомнить и передать" (store and forward), а момент передачи выбирается по заданному правилу (или явно инициируется, например, после восстановления связи).
Синхронный вариант оправдан, по-видимому, в примере с банком и его филиалами, приведенном в самом начале раздела (в случае асинхронного тиражирования появляется опасность, что нечистый на руку клиент банка может, к примеру, несколько раз закрыть свой счет, быстро перемещаясь из филиала в филиал, - впрочем, как показано ниже, данная проблема может быть разрешена и иначе). По сравнению с вариантом использования синхронной связи без тиражирования, преимущества состоят в том, что, во-первых, запросы выполняются на локальном сервере и не требуют передачи данных между серверами, во-вторых, транзакции, хотя и требуют распространения изменений, все же выполняются для клиентов быстрее, поскольку это распространение происходит асинхронно по отношению к транзакциям (клиент не ждет окончания обмена данными между серверами).
Другой важный пример использования синхронного тиражирования - поддержка "зеркальной" БД на резервном сервере, причем оба сервера (основной и резервный) в этом случае могут работать параллельно.
Что касается асинхронного тиражирования, то оно применимо тогда, когда нет возможности поддерживать постоянную связь между серверами, а временным рассогласованием данных можно поступиться (опять-таки в предположении, что состояние БД во времени предсказуемо). Если на Западе в качестве примера чаще всего приводят торгового агента, разъезжающего со своим ноутбуком и имеющего возможность лишь время от времени подключаться к сети, то в российских условиях, увы, аналогичная ситуация весьма типична. В тех регионах нашей могучей страны, где до сих пор самое надежное средство связи - это трактор, реализация даже предсказуемо работающего тиражирования данных представляется нелегкой задачей.
Впрочем, задача эта непроста и в случае, когда со связью все в порядке. Серьезной проблемой при проектировании системы является обеспечение ее корректного функционирования в условиях возможных конфликтов по обновлению различных копий одних и тех же данных на разных серверах. Здесь мы сталкиваемся с ситуацией, когда универсального решения попросту не существует, поэтому все, что может предоставить СУБД, - это средства для реализации различных вариантов решений и рекомендации по их использованию.
Прежде всего, необходимо выбрать общую архитектуру системы, точнее, тот ее аспект, который относится к дисциплине доступа к данным. Можно, конечно, никакой дисциплины не устанавливать, но в этом случае задача проектировщика становится наиболее сложной, да и стопроцентная гарантия корректности работы не всегда достигается. Впрочем, давайте по порядку.
Самый простой вариант архитектуры, заведомо гарантирующий отсутствие конфликтов, предполагает, что для любого тиражированного элемента данных среди всех равноправных хранителей его копий выбирается один, так сказать, самый равноправный. Ему одному разрешается этот элемент данных изменять, всем остальным дозволяется только наблюдать за этим. Вариантов реализации такой схемы может быть множество: от самого простого - звездообразного (филиалам банка разрешается видеть данные центрального отделения, но не изменять их) до гораздо более изощренных со сложной сетью неизменяемых снимков.
Более развитый вариант архитектуры, также дающий гарантию отсутствия конфликтов, разрешает динамическую передачу права модификации (в англоязычных материалах обычно употребляется термин, буквально переводимый как "документооборот") от сервера к серверу. Каждый элемент данных снабжается специальным атрибутом "разрешена запись", и вводится процедура передачи этого атрибута. Варианты реализации опять-таки могут быть различными. Характерным примером может служить информационная система торговой фирмы, где для каждого заказа эстафета последовательно передается от отдела продаж к управлению складом и далее к отделу доставки. Аналогичная схема в принципе решает упомянутую выше проблему "многократного закрытия счета" в банке.
Любые другие организации архитектуры тиражирования допускают возникновение конфликтов, следовательно, не остается ничего другого, как пытаться их разрешать. От СУБД здесь в первую очередь требуется обеспечить автоматическое обнаружение конфликтов и возможность извещения о них (наверное, излишне упоминать, что Oracle делает это), ибо момент возникновения конфликта зависит от механизма распространения изменений. Но просто извещать о проблеме и ждать ее "ручного" разрешения (по всей видимости, крайним, как всегда, окажется администратор БД) - вероятно, не лучший выход. По возможности нужно стремиться разрешать конфликты автоматически.
Oracle предлагает для этой цели набор процедур разрешения конфликтов, которые можно ассоциировать с группами столбцов таблицы. Руководствоваться при этом лучше всего здравым смыслом: скажем, если речь идет об описательных данных клиента, в качестве разрешающей функции разумно выбрать последнюю по времени модификацию, изменения количества товара на складе имеет смысл просуммировать и т. д.
Помимо внушительного набора стандартных функций разрешения конфликтов можно использовать и свои собственные. Однако не все так просто. Далеко не все функции способны обеспечить стопроцентную конвергенцию (непременную установку в одно и то же значение) данных, особенно в случае, когда в конфликте участвует более двух серверов. Если применяется нестандартная функция, для определения ее свойств может потребоваться весьма тонкий анализ (для стандартных он уже проведен). Как бы то ни было, в системе необходимо предусматривать либо выбор только тех функций, которые обеспечивают конвергенцию данных при принятой дисциплине доступа к ним, либо использовать извещение администратора, когда функция не способна справиться с ситуацией самостоятельно.
В качестве резюме отметим еще раз, что тиражирование дает чрезвычайно широкие возможности, но относиться к нему необходимо с большой осторожностью и тщательно анализировать все аспекты возможного поведения системы при ее проектировании.