Как использовать распределенную пользовательскую транзакцию вместо нескольких последних ресурсов, добавленных к текущей транзакции - PullRequest
0 голосов
/ 06 марта 2019

У меня есть war сервис с тремя моими заказными jar внутри. Каждый мой jar использует собственный источник данных. Итак, у меня есть три разных источника данных, определенные в моей конфигурации JBoss и соответствующий файл persistence.xml, где я к ним отношусь. Я могу изобразить это следующим образом: enter image description here Где у нас есть три службы: SM, RE и RA, и у каждого есть собственный источник данных. SM и RE используют источники данных для чтения и записи, но RA просто читает из БД. Порядок этих взаимодействий с источниками данных представлен в виде чисел возле стрелок на рисунке. Итак, изначально SM читает из БД, а в конце RE пишет в БД.

Мой вопрос: что мне нужно использовать, если я хочу в конце записать данные в оба источника данных, но в одну транзакцию?

Есть два возможных ответа, но оба меня не удовлетворяют:

  1. Используйте UserTransaction от JBoss в SM и RE, когда я хочу записать данные, и вручную обработать начало транзакции, а затем зафиксировать. Но здесь у меня слишком много дополнительных проблем, таких как WFTXN0001: A transaction is already in progress, даже если я никогда не начинал это раньше. Я не могу понять, как это работает, и я не могу найти краткую и понятную документацию или пример, где разъясняется использование UserTransaction. Итак, первый ответ - «это слишком сложно использовать, поэтому давайте использовать что-то еще».

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

<system-properties>
    <property name="com.arjuna.ats.arjuna.allowMultipleLastResources" value="true"/>
</system-properties>

Это работает! Однако в журнале есть предупреждение:

16:09:23,581 WARN  [com.arjuna.ats.arjuna] (default task-1) ARJUNA012141: Multiple last resources have been added to the current transaction. This is transactionally unsafe and should not be relied upon. Current resource is LastResourceRecord(XAOnePhaseResource(LocalXAResourceImpl@dbaabf3[connectionListener=767c209 connectionManager=78f5d4e2 warned=false currentXid=< formatId=131077, gtrid_length=29, bqual_length=36, tx_uid=0:ffff0ac03a90:74af3477:5c7fb46c:343, node_name=1, branch_uid=0:ffff0ac03a90:74af3477:5c7fb46c:35f, subordinatenodename=null, eis_name=java:/db3 > productName=PostgreSQL productVersion=9.6.2 jndiName=java:/db3]))
...
16:09:23,631 WARN  [com.arjuna.ats.arjuna] (default task-1) ARJUNA012141: Multiple last resources have been added to the current transaction. This is transactionally unsafe and should not be relied upon. Current resource is LastResourceRecord(XAOnePhaseResource(LocalXAResourceImpl@57a1383c[connectionListener=5ddce49c connectionManager=c66a93f warned=false currentXid=null productName=PostgreSQL productVersion=9.6.9 jndiName=java:/db2]))

Я хочу убежать от этих ужасных сообщений, но не могу, потому что JBoss ограничивает меня. Может быть, вы знаете другой способ, как без проблем использовать распределенную транзакцию на JBoss?

Спасибо.

P.S. Я не использую Spring. Мне запрещено его использовать.

1 Ответ

0 голосов
/ 06 марта 2019

Ну, не использовать Spring - не такая уж плохая вещь.

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

Какова ваша демаркация транзакции? Вы должны делать вызовы базы данных в том же контексте транзакции. Вам не нужно начинать пользовательскую транзакцию. Если вы используете аннотацию @Transactional в своем классе веб-службы, JBoss начнет транзакцию, и доступ к базе данных должен присоединиться к транзакции.

...