Классика баз данных - статьи

       

Атомарность XML-транзакций


Свойство атомарности транзакций означает, что все изменения, произведенные транзакцией над базой данных, либо будут после фиксации транзакции полностью присутствовать в базе данных и будут видны другим пользователям, либо ни одно изменение не будет внесено в базу данных. При декомпозиции XML-транзакции на субтранзакции SXTM необходимо гарантировать ее атомарность.

Если в РСУБД поддерживается модель вложенных транзакций ONT (Open Nested Transactions) [], то атомарность XML-транзакции можно реализовать средствами РСУБД. Основной характеристикой этой модели транзакций является то, что глобальная транзакция состоит из субтранзакций нижнего уровня, и при фиксации каждой субтранзакции полностью освобождаются ее блокировки. Тогда XML-транзакцию можно запускать в РСУБД как глобальную ONT-транзакцию, а отдельные операции XML выполнять как субтранзакции. В результате при откате XML-транзакции (или ее повторном выполнении) РСУБД по журналу может произвести все необходимые действия для обеспечения атомарности XML-транзакции.

Если РСУБД не поддерживает модель ONT, то SXTM разбивает исходную транзакцию на набор независимых DB-транзакций. В этом случае в SXTM должен присутствовать дополнительный менеджер восстановления XML-транзакций, поскольку в РСУБД ничего не известно о глобальной транзакции, и средствами РСУБД нельзя ее откатить (или повторно выполнить после сбоя). Менеджер восстановления в SXTM можно реализовать следующим образом.

SXTM должен заносить в журнал все изменения, производимые операциями модификации XML-документа. При фиксации каждой глобальной транзакции в журнал должна попадать соответствующая запись COMMIT. Журнал можно реализовать в виде дополнительной таблицы реляционной базы данных со следующей схемой:

SXTM-Log(LSN INT PRIMARY KEY, Transaction-ID INT, Operation VARCHAR(3), Parameters CLOB)

Первичным ключом таблицы SXTM-Log является столбец LSN (Log Sequence Number), значения которого уникально идентифицируют записи в журнале. В SXTM LSN можно реализовать на основе обычного счетчика, значение которого увеличивается на единицу при вставке очередной записи в журнал.
По LSN можно восстановить порядок следования операций модификации в глобальной транзакции. Столбец Transaction-ID содержит идентификатор глобальной XML-транзакции, к которой относится операция. В столбце Operation хранится тип операции модификации. Наконец, столбец Parameters хранит все параметры операции изменения.

Вставка в журнал SXTM-Log записи об операции модификации opi должна выполняться в рамках DB-транзакции, в которой выполняется эта операция. Таким образом, в случае мягкого сбоя системы (теряется содержимое основной памяти, но не повреждаются данные на диске) после восстановления базы данных средствами РСУБД в журнале SXTM-Log окажутся только записи для зафиксированных DB-транзакций. Других записей не будет, поскольку РСУБД гарантирует атомарность DB-транзакций.

Важным следствием этого свойства является то, что менеджеру восстановления SXTM никогда не требуется производить повторное выполнение (REDO) XML-операций, поскольку при выполнении операции фиксации XML-транзакции, когда производится вставка в журнал записи COMMIT для этой транзакции, происходит фиксация последней DB-транзакции. Таким образом, тот факт, что SXMT успешно зафиксировал XML-транзакцию, означает, что РСУБД успешно зафиксировала все субтранзакции, и поэтому при восстановлении после сбоя повторное выполнение всех субтранзакций будет выполнять РСУБД.

Другим важным обстоятельством является то, что для последней DB-транзакции в журнал не нужно помещать запись об XML-операции, выполняемой в этой транзакции, а достаточно вставить запись COMMIT. Это связано с тем, что SXTM никогда не откатывает последнюю DB-транзакцию (в случае сбоя эта транзакция всегда откатывается РСУБД).

Рассмотрим, какую информацию необходимо сохранять в столбце Parameters, чтобы можно было корректно выполнить отката (UNDO) для любой XML-операции модификации opi.



  • Пусть opi - это операция II. Для операции вставки узла обратной является операция удаления этого узла. В соответствии с семантикой операции II новый узел вставляется на место последнего ребенка целевого узла.




    Следовательно, обратная операция должна удалять последнего ребенка целевого узла. Например, для операции вставки InsertInto(<name&#x002F;>, &#x002F;doc&#x002F;person) в столбец Parameters нужно записать информацию об операции Delete&#x002F;doc&#x002F;person&#x002F;name[position() =last()]. При выполнении UNDO необходимо выполнить эту операцию удаления.
  • Пусть opi - это операция IB. Аналогично, в столбец Parameters нужно записать информацию об операции удаления вставленного узла. Например, для операции вставки InsertBefore(<name&#x002F;>, &#x002F;doc&#x002F;person&#x002F;hobby) в столбец Patrameters необходимо записать информацию об операции Delete(&#x002F;doc&#x002F;person&#x002F;hobby::preceding-sibling [ position()=1]). Для операции IA в последнем выражении необходимо заменить ось preceding-sibling на following-sibling.
  • Пусть opi - это операция D. Для операции удаления узла обратной является операция вставки этого узла. Поэтому удаляемый узел необходимо сохранить в журнале, чтобы при откате можно было его вставить. При этом требуется запомнить не только сам удаляемый узел, но и его позицию в XML-документе. Для этого перед выполнением операции удаления нужно выполнить предварительный запрос, результатом которого будут удаляемые узлы и их позиции в XML-документе. Например, для операции Delete(&#x002F;doc&#x002F;person[name='John']) предварительный запрос будет выглядеть так:

    for &#x0024;node at &#x0024;i in &#x002F;doc&#x002F;person where &#x0024;node&#x002F;name = 'John' return (&#x0024;node, &#x0024;i)

    Этот запрос выбирает все узлы person с именем "John", а также их позиции среди всех узлов person. Результат запроса сохраняется в столбце Parameters таблицы журнала. Кроме того, сохраняется путь в XML-документе, по которому нужно будет вставлять узлы при выполнении отката. Для рассматриваемого примера таким путем является &#x002F;doc.

    При выполнении обратной операции (UNDO) выполняются следующие действия:




    1. из столбца Parameters выбираются путь path, по которому нужно вставлять узлы, а также сами узлы node и их позиции pos в XML-документе,
    2. для каждого узла nodei выполняется операция вставки InsertAfter(nodei, path&#x002F;node()[position()=posi-1]).


    Для корректного выполнения этих действий необходимо гарантировать, что позиции удаленных и повторно вставляемых узлов в XML-документе не изменятся. Иначе после повторной вставки узел может попасть не на свое место в XML-документе. Для гарантии этого вводятся две дополнительные блокировки CD и LM, которые не совместимы одна с другой и обладают следующей семантикой.

    Блокировка CD (child delete) используется в операции D. Эта блокировка устанавливается на узел схемы, соответствующий родителю удаляемого узла. CD-блокировка, установленная на узел n, предотвращает какие-либо вставки или удаления детей узла n. Это гаратирует, что при откате операции D удаленные узлы будут вставляться в точности в те же позиции, в которых находились до операции удаления.

    Блокировка LM (level modified) используется в операциях I*, D и RN. Она устанавливается на узел схемы, состав дочерних узлов которого будет изменяться. Так, если транзакция вставляет новый узел в узел n, то на узел n, помимо блокировки SI необходимо установить еще и блокировку LM. Если транзакция вставляет новый узел перед узлом n, то на узел n должна быть установлена блокировка SB, а на родителя узла n - блокировка LM. При этом блокировка LM конфликтует с блокировкой CD.


    • Пусть opi - это операция RN. При выполнении этой операции происходит как удаление, так и вставка узла. Поэтому в журнал необходимо заносить информацию для повторной вставки переименовываемого узла и для удаления нового узла.


    В заключение раздела отметим, что при использовании описанного подхода к реализации в SXTM дополнительного менеджера восстановления XML-транзакций (если в РСУБД не поддерживается модель транзакций ONT) для операций D требуется выполнять дополнительный XQuery-запрос, а также приходится установливать дополнительные блокировки.Этих накладных расходов можно избежать, если использовать отложенную стратегию выполнения D операций.

    Основная идея заключается в том, что SXTM может отложить реальное выполнение операции удаления до тех пор, пока в этой же транзакции не понадобится выполнить какую-либо операцию, зависящую от результатов операции удаления, либо не произойдет фиксация транзакции. Если операция удаления выполняется в конце транзакции (при выполнении последней DB-транзакции), то в журнал уже не нужно писать какую-либо информацию по поводу этой операции, поскольку UNDO и REDO для последней DB-транзакции всегда выполняет РСУБД.

    При отложенном выполнении операции D SXTM должен установить обычные XDGL-блокировки для операции D в момент ее появления в транзакции, а LM- и CD-блокировки можно устанавливать непосредственно перед фактическим выполнением (возможно отложенном) операции D .


    Содержание раздела