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

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

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

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

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

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

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

5 ответов


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

некоторые люди укажут вам на XA, но XA (или двухфазная фиксация) - это ложь (или маркетолог).

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

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

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


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

try { 
    TransactionTemplate tt = new TransactionTemplate(txManager);

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

для получения дополнительных примеров и информации, возможно, посмотрите на это: XA транзакции с использованием Spring


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

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

Если, однако, вы просто имеете в виду две базы данных на одном сервере БД, то транзакции vanilla 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