2016-06-08 9 views
19

Предположим, у нас есть база данных (например, Oracle) и поставщик JMS (например, HornetQ), участвующий в транзакции XA. Сообщение отправляется в очередь JMS, а некоторые данные сохраняются в базе данных в той же распределенной транзакции. После совершения транзакции потребитель сообщения будет считывать сохраненные данные и обрабатывать их в отдельной транзакции.Согласование данных в транзакциях XA

Что касается первой транзакции XA, следующая последовательность событий может быть выполнена с помощью менеджера транзакций (например JBoss)

  1. подготовки (HornetQ)
  2. подготовки (Oracle)
  3. фиксации (HornetQ)
  4. фиксации (Oracle)

Что произойдет, если сообщение потребитель начинает считывать данные после совершения завершен в HornetQ, но все еще выполняется в Oracle? Будет ли пользователь сообщения читать устаревшие данные?

Вопрос может быть обобщен на любой вид нескольких ресурсов, участвующих в транзакциях XA, то есть есть возможность для небольшого временного окна (когда выполняются фазы фиксации), в котором читатель из другой параллельной транзакции может получить несогласованное состояние (путем считывания данных с одного ресурса и устаревших данных из другого)?

Я бы сказал, что единственный способ для транзакционных ресурсов предотвратить это - заблокировать всех читателей затронутых данных, как только этап подготовки будет завершен до тех пор, пока не будет произведена фиксация. Таким образом, упомянутый выше пример потребитель сообщения будет блокироваться до тех пор, пока данные не будут переданы в базу данных.

+0

Хороший вопрос, это основная проблема с JTA IMO, это не правильно документировано, даже спецификация слишком легка, чтобы описать (как должен) такой сложный механизм. –

+0

Кроме того, это не худший вариант использования, подумайте о случаях, когда у вас есть сбой при фиксации, когда разработчик XAResource не покрывает восстановление. –

+1

Подробные спецификации слишком длинны, чтобы ответить на них, но могут быть найдены в Oracle White Paper [«XA и Oracle контролируются распределенными Сделки»] (http://www.oracle.com/technetwork/products/clustering/overview/distributed -transactions-and-xa-163941.pdf) на стр. 12 в главе «Распределенные транзакции и блокировка базы данных». – ThinkJet

ответ

4

К сожалению, транзакции XA не поддерживают согласованность. При сопоставлении с CAP theorem XA разрешает доступность и допускаемость разделов в нескольких хранилищах данных. При этом он должен жертвовать консистенцией. При использовании XA вы должны принять возможную согласованность.

В любом случае создание систем, которые являются CP или AP, составляет hard enough, что независимо от вашего хранилища данных или транзакционной модели вы столкнетесь с этой проблемой.

1

У меня есть некоторый опыт работы с немного другой средой, основанной на Weblogic JMS и Oracle 11g. В этом ответе я полагаю, что он работает точно то же самое. Надеюсь, мой ответ вам поможет.

В нашем случае была «далекая» система, которая была обязательной для уведомления на основе различных событий, происходящих внутри локальной системы. Другая система также красная в нашей базе данных, поэтому прецедент кажется почти идентичным вашей проблеме. Последовательность событий была точно такой же, как ваша. На тестовых системах не было ни одного фалюра. Все думали, что это сработает, но некоторые из нас сомневаются, что это правильное решение. По мере запуска программного обеспечения некоторые из процессов BPM запускаются непредсказуемо. Поэтому простой ответ на ваш вопрос: да можно, и все должны знать об этом.

Наше решение (на мой взгляд) не было хорошо спланированным, но мы признали, что небольшое временное окно между двумя фиксаторами торможение системы, поэтому мы добавили некоторую «задержку» в очередь (если я помните, что это было как 1-2 минуты). Этого было достаточно, чтобы закончить другую фиксацию и прочитать согласованные данные. С моей точки зрения, это не лучшее решение. Он не решает проблему синхронизации (что, если транзакция оракула длиннее 1-2 мин?).

Here - отличное сообщение в блоге, которое стоит прочитать, и последнее решение кажется мне лучшим. Мы реализовали его в другой системе, и он работает лучше. Важно отметить, что вы должны ограничить повторы (повторное чтение), чтобы предотвратить «застрявшие» потоки. (с некоторыми сообщениями об ошибках). С этими ограничениями я пока не смог найти лучшего решения, поэтому, если у кого-то есть лучший вариант, я с нетерпением жду его услышать.:)

Редактировать: опечатки.

+0

«Что, если транзакция оракула длиннее 1-2 минут», то задержка, о которой мы говорим, - это время, чтобы зафиксировать транзакции, а не всей длительности транзакции, максимум в несколько десятков миллисекунд. Кроме того, сообщение JMS обычно отправляется по сети, которая должна занимать больше времени, чем только вторая фаза. По моему мнению, в вашем дизайне есть еще одна проблема. – Gab

+0

Это может быть проще решить путем приобретения блокировки данных, считываемых с потребителя сообщения (например, 'select for update'), чем с тайм-аутами? С тайм-аутами либо мы можем ввести слишком большую фиксированную задержку для каждого сообщения, либо увеличить риск повторного чтения устаревших данных, если таймаут слишком мал. –

+0

Простой замок не является шагом вперед, как я вижу. В момент считывания не будут представлены требуемые данные (вставка не наработана). Ручная синхронизация, о которой я говорил, является (на мой взгляд) способом более быстрого и надежного решения. Я вернусь из отпуска через 2 дня, если это потребуется. Я мог бы нарисовать блок-схему. На телефоне мои возможности довольно ограничены. – Mark

0

Да. Внешняя система может принимать и потреблять отправленные вами сообщения до, когда БД действительно совершает транзакции, даже если транзакция завершилась неудачей и после этого откатится.

В течение последних двух лет я занимался обслуживанием и разработкой распределенной системы с использованием транзакций XA с использованием WebSphere MQ в качестве поставщика JMS и Oracle 11g в качестве базы данных поддержки.
Одна из его партийных заданий будет читать автономные сообщения из БД, отправлять их в JMS и маркировать их как отправленные в БД - все это является частью одной и той же транзакции XA. Если какое-либо из сообщений или БД не удалось, транзакция будет отменена.

В некоторых случаях сообщение будет слишком большим для JMS и приведет к сбою send() и всей транзакции к откату(), оставив базу данных без изменений.
Однако внешний потребитель все еще получал и обрабатывал каждое сообщение, отправленное перед откатом. Я знал, потому что они отправили мне электронное письмо для каждого обработанного сообщения, и я получал много писем о сообщениях, которые не были помечены как отправленные в БД (поскольку транзакция была отброшена).

Если эта внешняя система каким-то образом выбрала SELECT COUNT (*) количество сообщений, отправленных моей системой, оно будет читать 0 отправленных сообщений, несмотря на то, что они уже потребляли сотни из них.

Итак, да, внешняя система может считывать устаревшие данные даже при использовании транзакций XA.

0

Я вставляю поле состояния, поэтому после каждого шага, если он был успешным, статус будет обновлен, и читатель должен проверить статус перед выполнением операции.