Qual è il modo "migliore" per effettuare transazioni distribuite su più database utilizzando Spring e Hibernate

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

Domanda

Ho un'applicazione, più simile a un'utilità, che si trova in un angolo e aggiorna periodicamente due database diversi.

È una piccola app standalone creata con un contesto di applicazione Spring. Il contesto ha due Hibernate Session Factories configurate al suo interno, a sua volta utilizzando origini dati DBCP Commons configurate in primavera.

Attualmente non esiste una gestione delle transazioni, ma vorrei aggiungerne alcune. L'aggiornamento a un database dipende da un aggiornamento riuscito all'altro.

L'app non si trova in un contenitore Java EE - è avviata da una classe di avvio statica chiamata da uno script di shell. La classe launcher crea un'istanza del contesto dell'applicazione e quindi richiama un metodo su uno dei suoi bean.

Qual è il modo "migliore" per mettere la transazionalità attorno agli aggiornamenti del database?

Lascio a te la definizione di "migliore", ma penso che dovrebbe essere una funzione di "facile da configurare", "facile da configurare", "economico" e "facile da impacchettare e ridistribuire". Naturalmente FOSS sarebbe buono.

È stato utile?

Soluzione

Il modo migliore per distribuire le transazioni su più di un database è: No.

Alcune persone ti indicheranno XA ma XA (o Two Phase Commit) è una bugia (o marketese).

Immagina: dopo che la prima fase ha comunicato al manager XA che può inviare il commit finale, la connessione di rete a uno dei database fallisce. E adesso? Tempo scaduto? Ciò lascerebbe corrotto l'altro database. Rollback? Due problemi: non è possibile ripristinare un commit e come si fa a sapere cosa è successo al secondo database? Forse la connessione di rete non è riuscita dopo aver eseguito correttamente il commit dei dati e solo il "successo" il messaggio è stato perso?

Il modo migliore è copiare i dati in un unico posto. Usa uno schema che ti consenta di interrompere la copia e continuarla in qualsiasi momento (ad esempio, ignora i dati che hai già o ordina la selezione per ID e richiedi solo i record > MAX (ID) della tua copia). Proteggilo con una transazione. Questo non è un problema poiché stai solo leggendo i dati dall'origine, quindi quando la transazione fallisce per qualsiasi motivo, puoi ignorare il database di origine. Pertanto, questa è una semplice transazione single source.

Dopo aver copiato i dati, elaborali localmente.

Altri suggerimenti

Imposta un gestore transazioni nel tuo contesto. I documenti di primavera hanno degli esempi ed è molto semplice. Quindi, quando si desidera eseguire una transazione:

try { 
    TransactionTemplate tt = new TransactionTemplate(txManager);

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

Per ulteriori esempi, e forse le informazioni danno un'occhiata a questo: Transazioni XA utilizzando Spring

Quando dici "due database diversi", intendi server di database diversi o due schemi diversi all'interno dello stesso server DB?

Se il primo, quindi se si desidera la piena transazionalità, è necessario l'API di transazione XA, che fornisce il commit in due fasi completo. Ma soprattutto, è necessario anche un coordinatore / monitor delle transazioni che gestisca la propagazione delle transazioni tra i diversi sistemi di database. Questo fa parte delle specifiche JavaEE e una parte piuttosto rarefatta di ciò. Il coordinatore TX stesso è un software complesso. Il software applicativo (tramite Spring, se lo desideri) parla con il coordinatore.

Se, tuttavia, intendi solo due database all'interno dello stesso server DB, le transazioni JDBC alla vaniglia dovrebbero funzionare bene, esegui le tue operazioni su entrambi i database all'interno di una singola transazione.

In questo caso avresti bisogno di un Transaction Monitor (server che supporta il protocollo XA) e assicurati che anche i tuoi database supportino XA. La maggior parte (tutti?) Dei server J2EE viene fornito con Transaction Monitor integrato. Se il codice non è in esecuzione nel server J2EE, ci sono un sacco di alternative standalone: ??Atomicos, Bitronix, ecc.

Potresti provare Spring ChainedTransactionManager - http://docs.spring.io/spring-data/commons/docs/1.6.2.RELEASE/api/org/springframework/data/transaction/ChainedTransactionManager.html che supporta transazioni db distribuite. Questa potrebbe essere una migliore alternativa a XA

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top