Начнем с того, что этот вопрос не касается применения внешнего менеджера транзакций XA, поскольку это определенно решит проблему.Вопрос заключается в том, как обойтись без этого, предполагая следующее:
- Транзакции в обеих базах данных выполняются в одном потоке Java
- Данные считываются и записываются из / в обе базы данных, кака также другие нетранзакционные источники и места назначения
- Неверное согласование данных между двумя базами данных НЕ требуется
- Приемлема оптимистическая фиксация 1PC (сбой 2-й фиксации не должен вызывать откат для 1-й базы данных)
- Программный или декларативный контроль объема транзакций в порядке
Теперь давайте предположим следующий сценарий:
- Начать транзакцию X для дБ A
- Readи записать некоторые данные в дБ A
- На основании этих данных иногда мне нужно использовать db B
- (продолжать работать в том же потоке Java)
- Начать транзакцию Y длядБ B
- Чтение и запись некоторых данных в дБ B
- Если что-то не получается, откат ОБА транзакций
- Подтверждение транзакции Y
- Эффективно возобновить транзакцию X
- Считать и записать еще больше данных в дБ A
- Если что-то не получается, откатить транзакцию X только
- Подтвердитьтранзакция X
Как мне кажется, все требует решения "вложенной транзакции", которое, к счастью, поддерживается Spring DataSourceTransactionManager
.Проблема заключается в том, что Propagation.NESTED
предполагает, что транзакции X и Y выполняются в одной и той же базе данных (DataSource
) и, возможно, в одной и той же базовой JDBC Connection
.Но это явно не тот случай, который у меня есть, поскольку базы данных имеют отдельные соединения и способны поддерживать независимые транзакции.
Другое возможное решение, которое я попробовал, - создать два экземпляра DataSourceTransactionManager
, по одному для каждой базы данных.На первый взгляд, это выглядит более чистым решением, но потом я понял, что стандартные классы Spring в значительной степени полагаются на статические, локальные по потоку поля, гарантируя тем самым помехи друг другу при попытке одновременно использовать два менеджера в одном и том же потоке (см. Предположение выше).).Нет.
Теперь я подумываю о создании подкласса всех соответствующих классов управления транзакциями Spring, чтобы «разделить» эти общие статические поля между пакетами.Однако все равно что изобретать велосипед, поэтому я бы предпочел этого не делать.
Поскольку внешний менеджер транзакций XA воспринимается как излишнее (из-за очень слабых требований согласованности, см. Выше), это единственное решениеперейти на уровень JDBC и программно управлять транзакцией Y (начать, читать, записывать данные, фиксировать)?Или мне не хватает какой-то продвинутой концепции в spring-tx
?