Каков «лучший» способ распределенных транзакций между несколькими базами данных с использованием Spring и Hibernate - PullRequest
29 голосов
/ 24 сентября 2008

У меня есть приложение - больше похожее на утилиту - которое сидит в углу и периодически обновляет две разные базы данных.

Это небольшое автономное приложение, созданное с помощью Spring Application Context. В контексте настроены две фабрики сеансов Hibernate, в свою очередь использующие источники данных Commons DBCP, настроенные в Spring.

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

Приложение не находится в контейнере Java EE - оно загружается статическим классом запуска, вызываемым из сценария оболочки. Класс запуска создает экземпляр Application Context, а затем вызывает метод на одном из его bean-компонентов.

Каков наилучший способ обеспечить транзакционность обновлений базы данных?

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

Ответы [ 5 ]

30 голосов
/ 20 мая 2009

Лучший способ распределить транзакции по нескольким базам данных: не делать.

Некоторые люди укажут вам на XA, но XA (или Two Phase Commit) - ложь (или маркетолог).

Представьте себе: после того, как на первом этапе менеджер XA сообщил, что он может отправить окончательную фиксацию, сетевое соединение с одной из баз данных перестает работать. Что теперь? Тайм-аут? Это оставит другую базу данных поврежденной. Откат? Две проблемы: вы не можете откатить коммит и как узнать, что случилось со второй базой данных? Может быть, сетевое соединение не удалось после того, как он успешно зафиксировал данные, и было потеряно только сообщение об успехе?

Лучший способ - скопировать данные в одном месте. Используйте схему, которая позволяет прервать копию и продолжить ее в любое время (например, игнорировать данные, которые у вас уже есть, или заказать выбор по идентификатору и запрашивать только записи> MAX (ID) вашей копии). Защитите это с помощью транзакции. Это не проблема, поскольку вы только читаете данные из источника, поэтому, когда транзакция завершается неудачей по любой причине, вы можете игнорировать исходную базу данных. Таким образом, это простая старая транзакция с одним источником.

После того, как вы скопировали данные, обработайте их локально.

6 голосов
/ 24 сентября 2008

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

try { 
    TransactionTemplate tt = new TransactionTemplate(txManager);

    tt.execute(new TransactionCallbackWithoutResult(){
    protected void doInTransactionWithoutResult(
            TransactionStatus status) {
        updateDb1();
        updateDb2();
    }
} catch (TransactionException ex) {
    // handle 
}

Дополнительные примеры и информацию, возможно, смотрите на это: транзакции XA с использованием Spring

5 голосов
/ 28 сентября 2008

Когда вы говорите «две разные базы данных», подразумеваете ли вы разные серверы баз данных или две разные схемы в одном и том же сервере БД?

Если первое, то если вам нужна полная транзакционность, вам нужен API транзакций XA, который обеспечивает полную двухфазную фиксацию. Но что еще более важно, вам также нужен координатор / монитор транзакций, который управляет распространением транзакций между различными системами баз данных. Это часть спецификации JavaEE, и в этом довольно редкая часть. Координатор TX сам по себе является сложным программным обеспечением. Ваше прикладное программное обеспечение (через Spring, если вы того пожелаете) общается с координатором.

Однако, если вы просто имеете в виду две базы данных на одном и том же сервере БД, тогда ванильные JDBC-транзакции должны работать нормально, просто выполняйте операции с обеими базами данных в одной транзакции.

3 голосов
/ 12 июня 2014

Вы можете попробовать Spring ChainedTransactionManager - http://docs.spring.io/spring-data/commons/docs/1.6.2.RELEASE/api/org/springframework/data/transaction/ChainedTransactionManager.html, который поддерживает распределенную транзакцию БД. Это может быть лучшей альтернативой XA

3 голосов
/ 28 декабря 2008

В этом случае вам потребуется Transaction Monitor (сервер, поддерживающий протокол XA) и убедитесь, что ваши базы данных также поддерживают XA. Большинство (все?) J2EE-серверов поставляется со встроенным Transaction Monitor. Если ваш код работает не на J2EE-сервере, то есть множество автономных альтернатив - Atomicos, Bitronix и т. Д.

...