XA
XA Транзакции впервые были описаны в XA Specification в 1992 году. Несмотря на столь почтенный возраст, спецификация является обязательной для реализации в менеджерах распределенных транзакций и реляционных базах данных. Спецификация решает задачу совместного участия транзакционных ресурсов в транзакции (распределенность).
История
К началу 90-х годов прошлого столетия существовало огромное множество стандартов распределенных транзакций, например, TPF, используемый и по сей день в гражданской авиации США[1], CISC, VMS и другие. Один из них, SNA от IBM стал к тому времени стандартом de facto. Под влиянием этого стандарта и стандарта LU6.2 ISO создала несколько новых стандартов[2]
- Remote Operations Services (ROSE), определяющий как клиент вызывает сервер
- Commit, Concurrency Control, and Recovery (OSI-CCR), определяющий сообщение фиксации (commit) в пределах одной сессии
- Transaction Processing (OSI-TP), определяющий, как следует создавать идентификаторы транзакций и как ими управлять
Основным недостатком этих стандартов было отсутствие API, таким образом, они сообщали как менеджеры транзакций должны взаимодействовать, но не предоставляли правил написания переносимых приложений.
X/Open решило эту проблему предоставив модель распределенных транзакций, и, одновременно с этим, специфицировав процедурный интерфейс взаимодействия участников транзакции (CLI), спецификацию XA.
Транзакция
Транзакция — это операция, обладающая свойствами атомарности, согласованности, изолированности и долговечности (ACID). В XA используется модель распределенных транзакций, описанная в модели распределенных транзакций[3] в том же 1992 году. Согласно этой модели система распределенных транзакций состоит из трех компонент:
- Прикладная программа (AP) — программа, определяющая, из каких частей должна состоять транзакция, какие RM использовать и так далее. По сути именно здесь описывается бизнес-логика.
- Менеджер распределенных транзакций (TM) — он же координатор, координирует работу RM и принимает решение о закреплении или откате транзакции, используя двухфазный протокол фиксации транзакции (Two-Phase Commit Protocol).
- Менеджеры ресурсов (RM), такие как СУБД, используются для хранения информации.
Несмотря на то, что в модели фигурируют три компонента, спецификация XA определяет только взаимодействие между менеджерами ресурсов и транзакций.
Спецификация XA разделяет транзакции на локальные и глобальные.
Локальные транзакции
Самый простой вид транзакций. В них прикладная программа обращается только к одной СУБД и сама определяет, когда закреплять или откатывать транзакцию. То есть в них роль TM отводится AP.
Распределенные транзакции
То, ради чего и написана спецификация. Намного более сложный случай, но, несмотря на это прикладной код усложняется ненамного, решение о закреплении или откате ложится на плечи координатора, прикладная программа определяет только границы транзакций.
Менеджер транзакций делит одну глобальную на несколько веток (branch), которые с большой натяжкой можно назвать локальными.
Как это происходит? Допустим, есть два RM, которые участвуют в распределенной транзакции.
- AP начинает транзакцию. Управление передается TM.
- Для каждой из них TM вызывает xa_open() для инициализации. Транзакции как таковой ещё нет.
- Для каждой RM вызывается xa_start() с параметром xid, в котором global_id одно, а branch_id разные. Транзакция началась.
- Управление возвращается AP, которая выполняет бизнес-логику.
- TM завершает транзакцию, вызывая xa_end().
- TM закрепляет транзакцию, используя протокол двухфазной фиксации (xa_prepare() и xa_commit() или xa_rollback()).
Кроме того, спецификация поддерживает вложенные транзакции (nested transactions), которые полезны, например, для логирования.
- TM «завершает» ветвь транзакции, вызывая xa_end() с параметром XA_SUSPEND.
- TM обрабатывает вложенную транзакцию.
- TM «начинает» «завершенную» ветвь, вызывая xa_start() с параметром XA_RESUME.
Возможные оптимизации
Иногда протокол двухфазной фиксации оказывается излишним. Тогда возникает вопрос о корректном завершении транзакции. К счастью, в XA описаны специальные случаи, в которых возможна оптимизация протокола.
Чтение
Если в одной из ветвей транзакции не происходит изменения данных, то после фазы prepare TM не начинает вторую фазу, так как закреплять просто нечего.
Однофазное закрепление
Если транзакция состоит из одной ветви, то отпадает необходимость в первой фазе, TM сразу закрепляет транзакцию.
Несколько AP
В спецификации XA+, выпущенной в 1994 году, определяются также транзакции, распределенные относительно приложений. В XA+ появляется ещё один участник транзакции
- Communication Resource Manager (CRM) — отвечает за взаимодействие между несколькими TM.
В данном виде транзакций роль координатора распределенных транзакций падает на плечи CRM, вместо TM. Именно он отвечает за новые ветви транзакции, которые, в свою очередь, содержат ещё несколько ветвей. Также он отвечает за генерацию идентификаторов транзакций.
Два примера распределенных транзакций подробно рассмотрены в разделе B.1 спецификации XA+, поэтому останавливаться на них не будем.
Восстановление транзакции
[4][5] Что произойдет, если глобальная транзакция будет прервана? Например, после того, как спишут деньги с одного счета, доступ к базе данных будет потерян. В спецификации XA о восстановлении после сбоев сказана буквально пара слов, несмотря на то, что при этом теряется свойство атомарности транзакции. К счастью и этой пары слов хватает для того, чтобы понять, как необходимо поступать компонентам транзакционной системы в случае отказа. Для того, чтобы при повторном запуске менеджера распределенных транзакций он мог понять, на какой стадии произошёл сбой, он ведет лог транзакции, куда записывается информация о начале, и обоих фазах завершения транзакции[6][7].
Рассмотрим несколько сценариев.
- Отказ произошёл до фазы prepare
- Отказ произошёл во время фазы prepare
- Отказ произошёл после фазы prepare до фазы commit
- Отказ произошёл во время фазы commit
Очевидно, что вариантов отказа может быть множество, от рассмотренной потери связи с базой данных до отключения электричества.
Отказ произошел до фазы prepare
Допустим, до фазы prepare TM потерял связь с RM, тогда, во время фазы prepare он получит ошибку подключения, и откатит транзакцию. Допустим, теперь, что RM «завис», то есть подключение есть, но СУБД не отвечает на запросы. Чтобы не ждать, пока СУБД «отвиснет», TM должен выждать некоторое время (timeout) и откатить транзакцию. СУБД же откатит её, так как для неё не было фазы prepare.
И наконец, допустим, что падает само приложение или с ним теряется связь, либо от TM в течение долгого времени не приходит запроса prepare. В данном случае СУБД выжидает таймаут и само откатывает транзакцию. В случае, если TM отправит prepare, СУБД сообщит об эвристическом откате транзакции. (эвристически завершенная ветвь транзакции — это ветвь, которая была закреплена или откачена до фазы prepare)[6][8]
Отказ произошел во время фазы prepare
Возьмем в качестве примера операцию перевода денег с одного счета на другой. Пусть после операции списания (кредит) и до операции зачисления (дебет) произошёл отказ.
Допустим, что проблемы на стороне дебетовой СУБД. В данном случае TM и кредитовая СУБД откатят транзакцию по истечении таймаута. Дебетовая СУБД также откатит её, так как для неё не было фазы prepare.
Допустим, что проблемы на стороне TM (процесс неожиданно завершился), так как ведется лог транзакции, в нём будет указано какие СУБД уже прошли фазу prepare, а какие ждут своей очереди. Вызвав после старта функцию xa_recover() для каждого RM, он получит список ветвей, которые были эвристически завершены и которые прошли фазу prepare. Отсеяв из них свои ветки (по полю global_id xid’а), он вызовет xa_rollback() для тех, что подготовлены к закреплению и xa_forget() для остальных. В данном примере операция кредита будет откатана, а операция дебета — забыта, так как СУБД уже откатила её.
Остальные случаи
- Отказ на стороне СУБД
После поднятия СУБД, TM вызовет xa_recover() и завершит транзакцию.
- Отказ на стороне TM
После старта TM прочтет из лога информацию о незавершенных транзакциях, завершит вторую фазу 2PC и закрепит транзакцию.
Стандарты, основанные на XA
Несмотря на то, что XA специфицирует API лишь для языка С, существуют реализации и на других языках программирования.
Кроме того, эта спецификация, в явном или неявном виде входит во многие фреймворки, такие как Java EE и .NET. В этих фреймворках решена задача демаркации транзакций.
Java EE
В 1999 году Sun представила J2EE версии 1.2, в составе которого содержалась спецификации Java Transaction API, которая, в свою очередь содержала интерфейс XAResource. Именно XAResource и есть перевод на объектный язык интерфейса xa.h. По сути, прикладной программист никогда не увидит этого интерфейса, так как этими ресурсами управляет менеджер транзакций. Программисту нужно лишь описать границы транзакций и бизнес логику.
.NET
В .NET Framework поддержка распределенных транзакций появилась лишь в версии 2.0, аналогично Java EE, программист не работает непосредственно с XA, он лишь определяет бизнес логику приложения и участие в транзакции. Стоит отметить, что кроме XA, .NET поддерживает и OLE.[9]
XA и OTS
В 1991 году Object Management Group (OMG) представила миру спецификацию Object Transaction Service (OTS), которая вносит транзакционность в Common Object Request Broker Architecture (CORBA). Благодаря тому, что спецификация не разделяла участников транзакции на RM и TM, только на клиент и сервер, стало возможно использовать XA и OTS в одном клиент-серверном приложении. Кроме того, если один из RM не поддерживал XA, но поддерживал OTS, то эта связка является единственно возможным решением проблемы распределенных транзакций в данном окружении.
Java EE
Связка XA и OTS используется в Java EE, где оберткой над OTS является Java Transaction Service(JTS), а JTA в свою очередь отделяет JTS от AP.
Ссылки
- ↑ См Transaction Processing: Concepts and Techniques, раздел 1.5
- ↑ См Transaction Processing: Concepts and Techniques, раздел 2.7.4
- ↑ https://www2.opengroup.org/ogsys/jsp/publications/PublicationDetails.jsp?publicationid=11415 - DTP model
- ↑ Информация взята из книги Java Transaction Processing: Design and Implementation
- ↑ Transaction processing: concepts and techniques — Part 5 — Recovery
- ↑ 1 2 http://docs.oracle.com/cd/E15051_01/wls/docs103/jta/trxman.html - подробнее для WebLogic
- ↑ http://msdn.microsoft.com/en-us/library/ms189275.aspx - для MS SQL Server
- ↑ Web Services Transactions and Heuristics / Mark Little / weblog / WebServices.Org
- ↑ INFO: Connections May Not Participate in MTS/COM+ Transactions When You Use OLE DB Directly