Подтвердить что ты не робот

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

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

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

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

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

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

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

4b9b3361

Ответ 1

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

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

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

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

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

Ответ 2

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

try { 
    TransactionTemplate tt = new TransactionTemplate(txManager);

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

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

Ответ 3

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

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

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

Ответ 4

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