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

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

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

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

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

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

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


person Vihung    schedule 24.09.2008    source источник


Ответы (5)


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

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

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

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

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

person Aaron Digulla    schedule 20.05.2009
comment
Распределенные транзакции должны соответствовать всем 4 свойствам ACID. В чем твоя проблема? Описанный вами сценарий не может произойти, так как менеджеры общаются друг с другом и совершают коммит только тогда, когда все участвующие узлы обменялись GO. - person Falcon; 05.01.2011
comment
@Falcon: Итак, что произойдет, если сеть выйдет из строя между PREPARE и COMMIT? Или один из серверов умирает? не может случиться не может случиться в реальности. - person Aaron Digulla; 07.01.2011
comment
Нет, им не дается указание откатиться, потому что в этом сценарии некоторые узлы уже зафиксированы. Что происходит, когда разбившийся узел становится доступным, координатор транзакций говорит ему снова зафиксировать. Поскольку узел дал положительный ответ на этапе подготовки, требуется, чтобы он был в состоянии зафиксировать, даже когда он возвращается после сбоя. - person K.Nicholas; 30.03.2016
comment
@Nicholas ... если вы больше не можете запустить узел из-за аппаратного сбоя. - person Aaron Digulla; 02.04.2016
comment
Я думаю, что диск RAID решит эту проблему или даже сделает резервные копии. Восстановите последнюю хорошую точку резервного копирования, и все потерянные коммиты будут применены повторно. - person K.Nicholas; 02.04.2016
comment
@Nicholas: Нет, не будут, потому что резервной копии несколько часов, а резервные копии разных серверов не будут совпадать. Я понимаю, что вы хотите, чтобы XA работал, потому что это кажется хорошим решением, но на самом деле это не так. Под поверхностью скрываются буквально тысячи проблем, и одна из них в конце концов испортит вам день. - person Aaron Digulla; 04.04.2016
comment
Я понимаю, что вы хотите, чтобы он не работал, но я полагаю, что есть много мест в мире, которые работают с ним довольно успешно и у которых были проблемы с оборудованием. - person K.Nicholas; 04.04.2016
comment
@Nicholas Я работал в тех местах, и все в конце концов отказались от XA, потому что они не могли заставить его работать надежно, даже потратив миллионы долларов. - person Aaron Digulla; 04.04.2016
comment
Я считаю, что поддержка стандарта слишком широко распространена, чтобы на нее повлияли анекдотические свидетельства одного человека. Спасибо за ваши Коментарии. - person K.Nicholas; 04.04.2016
comment
@Nicholas Я считаю, что поддержка широко распространена только у компаний, которые зарабатывают деньги, устраняя проблемы, создаваемые этим стандартом. Потребители (= люди, которым приходится страдать от таких решений) обычно пробуют это один раз, а затем ищут лучшие решения. Тем не менее, мой ответ логичен. Мой подход намного проще, чем XA, и я могу доказать, что он всегда будет работать. XA — это скорее обещание, а не факт. - person Aaron Digulla; 19.04.2016
comment
Я ничего не говорил о вашем решении. Я использовал его сам. Это немного замедляет работу, но может быть выполнено, когда XA непомерно дорого стоит. Архитектуры распределенных баз данных прекрасно работают, если их внедряет компетентная группа по работе с базами данных. - person K.Nicholas; 19.04.2016
comment
Пожалуйста, поддержите меня здесь, братан ?noredirect=1#comment66502135_39584339" title="перехватывать транзакцию только тогда, когда она обязательно будет зафиксирована, но до фиксации"> stackoverflow.com/questions/39253524/ - person Derrops; 21.09.2016
comment
Я думаю, что вы нужны здесь: =1#comment73317290_43118778" title="транзакция в двух таблицах одновременно в двух разных базах данных"> stackoverflow.com/questions/43118778/ :) - person ; 30.03.2017

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

try { 
    TransactionTemplate tt = new TransactionTemplate(txManager);

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

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

person Community    schedule 24.09.2008
comment
Этот пример на самом деле не отвечает на вопрос или даже отвечает на него неправильно: ОП упомянул, что у него настроены две фабрики сеансов Hibernate, для которых потребуются два отдельных менеджера транзакций. В примере в ответе используется только один диспетчер транзакций, который не указан ближе. Следовательно, использование одного менеджера транзакций Hibernate никогда не приведет к откату одной из двух баз данных при ошибках. Использование, например, ChainedTransactionManager (как отметил @Pani Dhakshnamurthy) может помочь, но это не упоминается в этом ответе. - person Chriki; 16.07.2015

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

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

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

person skaffman    schedule 28.09.2008

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

person maximdim    schedule 28.12.2008

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

person Pani Dhakshnamurthy    schedule 12.06.2014