Как работать с базой данных B в рамках транзакции, управляемой Spring, в базе данных A без XA? - PullRequest
0 голосов
/ 07 июня 2019

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

  • Транзакции в обеих базах данных выполняются в одном потоке Java
  • Данные считываются и записываются из / в обе базы данных, кака также другие нетранзакционные источники и места назначения
  • Неверное согласование данных между двумя базами данных НЕ требуется
  • Приемлема оптимистическая фиксация 1PC (сбой 2-й фиксации не должен вызывать откат для 1-й базы данных)
  • Программный или декларативный контроль объема транзакций в порядке

Теперь давайте предположим следующий сценарий:

  1. Начать транзакцию X для дБ A
  2. Readи записать некоторые данные в дБ A
  3. На основании этих данных иногда мне нужно использовать db B
    • (продолжать работать в том же потоке Java)
    • Начать транзакцию Y длядБ B
    • Чтение и запись некоторых данных в дБ B
    • Если что-то не получается, откат ОБА транзакций
    • Подтверждение транзакции Y
  4. Эффективно возобновить транзакцию X
  5. Считать и записать еще больше данных в дБ A
  6. Если что-то не получается, откатить транзакцию X только
  7. Подтвердитьтранзакция X

Как мне кажется, все требует решения "вложенной транзакции", которое, к счастью, поддерживается Spring DataSourceTransactionManager.Проблема заключается в том, что Propagation.NESTED предполагает, что транзакции X и Y выполняются в одной и той же базе данных (DataSource) и, возможно, в одной и той же базовой JDBC Connection.Но это явно не тот случай, который у меня есть, поскольку базы данных имеют отдельные соединения и способны поддерживать независимые транзакции.

Другое возможное решение, которое я попробовал, - создать два экземпляра DataSourceTransactionManager, по одному для каждой базы данных.На первый взгляд, это выглядит более чистым решением, но потом я понял, что стандартные классы Spring в значительной степени полагаются на статические, локальные по потоку поля, гарантируя тем самым помехи друг другу при попытке одновременно использовать два менеджера в одном и том же потоке (см. Предположение выше).).Нет.

Теперь я подумываю о создании подкласса всех соответствующих классов управления транзакциями Spring, чтобы «разделить» эти общие статические поля между пакетами.Однако все равно что изобретать велосипед, поэтому я бы предпочел этого не делать.

Поскольку внешний менеджер транзакций XA воспринимается как излишнее (из-за очень слабых требований согласованности, см. Выше), это единственное решениеперейти на уровень JDBC и программно управлять транзакцией Y (начать, читать, записывать данные, фиксировать)?Или мне не хватает какой-то продвинутой концепции в spring-tx?

1 Ответ

0 голосов
/ 25 июня 2019

Я не эксперт по Spring (поэтому я не могу ничего сказать о идее подкласса), но я знаю, что транзакции Spring используют возможности JTA.

Как вы сказали, DataSourceTransactionManager работаеттолько для ресурса и NESTED функциональность возможна из-за API JDBC и его функциональности для работы с безопасными точками (https://docs.oracle.com/javase/8/docs/api/java/sql/Connection.html#setSavepoint--). Эта способность ограничена одним Connection.

Я думаю, что вы можете пойтис ручным управлением JDBC, как вы предложили. Или я все равно рассмотрел бы диспетчер транзакций. Менеджер транзакций не только управляет транзакциями XA, но и обеспечивает реализацию API JTA, поскольку вы можете использовать декларативный или программный подход. Наибольшие накладные расходы для транзакцииУправление - это обработка XA - данные должны быть сохранены на диске во время подготовки в приложении и на стороне базы данных. Если вы используете только возможность управления транзакциями с не-XA-ресурсом, тогда менеджер транзакций дает вам JTA API для выполнения транзакции., не обеспечивает составency (это не то, что вам нужно) и не использует накладные расходы XA.

Если вы используете диспетчер транзакций и два не-XA-ресурса (DriverManagerDataSource), то вы можете управлять транзакциями, такими как - начало - обновление данных - приостановка# 1 - начать - обновить данные - зафиксировать # 2 - возобновить # 1 - зафиксировать.

К сожалению, ваш конкретный случай лучше всего подходит для модели вложенных транзакций, которая не поддерживается в JTA.Но даже с прицелом NESTED Spring этот чехол - именно то, что вам нужно.Вложенная схема работает таким образом, что, если вложенная транзакция откатывается, внешняя транзакция не откатывается автоматически.Другими словами, откат вложенной транзакции (транзакция Y) не означает, что внешняя транзакция также откатывается (транзакция X).

...