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

StackOverflow https://stackoverflow.com/questions/128377

Вопрос

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

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

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

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

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

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

Это было полезно?

Решение

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

Некоторые люди укажут вам на XA, но XA (или Two Phase Commit) — это ложь (или рыночная версия).

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

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

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

Другие советы

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

try { 
    TransactionTemplate tt = new TransactionTemplate(txManager);

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

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

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

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

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

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

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top