Подтвердить что ты не робот

Согласованность данных в транзакциях XA

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

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

  • подготовить (HornetQ)
  • подготовить (Oracle)
  • commit (HornetQ)
  • commit (Oracle)

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

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

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

4b9b3361

Ответ 1

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

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

Ответ 2

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

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

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

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

Изменить: опечатки.

Ответ 3

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

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

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

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

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

Ответ 4

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