¿Cuál es la "mejor" manera de hacer transacciones distribuidas en múltiples bases de datos utilizando Spring e Hibernate?

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

Pregunta

Tengo una aplicación, más como una utilidad, que se encuentra en un rincón y actualiza periódicamente dos bases de datos diferentes.

Es una pequeña aplicación independiente que se ha creado con un contexto de aplicación Spring. El contexto tiene dos Fábricas de sesión de Hibernate configuradas en él, a su vez, utilizando fuentes de datos Commons DBCP configuradas en Spring.

Actualmente no hay administración de transacciones, pero me gustaría agregar algunas. La actualización a una base de datos depende de una actualización exitosa a la otra.

La aplicación no se encuentra en un contenedor de Java EE: es iniciada por una clase de iniciador estático llamada desde un script de shell. La clase de iniciador crea una instancia del contexto de la aplicación y luego invoca un método en uno de sus beans.

¿Cuál es la "mejor" manera de poner la transaccionalidad en las actualizaciones de la base de datos?

Le dejaré la definición de 'mejor', pero creo que debería ser una función de 'fácil de configurar', 'fácil de configurar', 'económico' y 'fácil de empaquetar y redistribuir'. Naturalmente FOSS sería bueno.

¿Fue útil?

Solución

La mejor forma de distribuir transacciones en más de una base de datos es: no.

Algunas personas te señalarán a XA, pero XA (o Two Phase Commit) es una mentira (o comercial).

Imagínese: Después de que la primera fase le haya dicho al administrador de XA que puede enviar el compromiso final, la conexión de red a una de las bases de datos falla. ¿Ahora que? ¿Se acabó el tiempo? Eso dejaría la otra base de datos corrupta. ¿Retroceder? Dos problemas: no puede revertir un compromiso y ¿cómo sabe lo que pasó con la segunda base de datos? Es posible que la conexión de red haya fallado después de haber confirmado correctamente los datos y solo el " éxito " ¿Se perdió el mensaje?

La mejor manera es copiar los datos en un solo lugar. Use un esquema que le permita abortar la copia y continuarla en cualquier momento (por ejemplo, ignore los datos que ya tiene o solicite la selección por ID y solicite solo los registros > MAX (ID) de su copia). Protege esto con una transacción. Esto no es un problema ya que solo está leyendo datos del origen, por lo que cuando la transacción falla por cualquier motivo, puede ignorar la base de datos de origen. Por lo tanto, esta es una transacción simple de una sola fuente.

Una vez que haya copiado los datos, procesarlos localmente.

Otros consejos

Configure un administrador de transacciones en su contexto. Los documentos de primavera tienen ejemplos, y es muy simple. Luego, cuando quieres ejecutar una transacción:

try { 
    TransactionTemplate tt = new TransactionTemplate(txManager);

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

Para más ejemplos, e información quizás vea esto: XA transacciones usando Spring

Cuando dices "dos bases de datos diferentes", ¿te refieres a servidores de bases de datos diferentes, o dos esquemas diferentes dentro del mismo servidor DB?

Si es el primero, si desea una transaccionalidad completa, necesita la API de transacción XA, que proporciona un compromiso de dos fases completo. Pero lo que es más importante, también necesita un coordinador / monitor de transacciones que gestione la propagación de transacciones entre los diferentes sistemas de bases de datos. Esto es parte de la especificación JavaEE, y es una parte bastante rara en eso. El coordinador de TX en sí es una pieza compleja de software. Su software de aplicación (a través de Spring, si así lo desea) habla con el coordinador.

Sin embargo, si solo te refieres a dos bases de datos dentro del mismo servidor de base de datos, entonces las transacciones JDBC de vanilla deberían funcionar bien, simplemente realiza tus operaciones contra ambas bases de datos dentro de una sola transacción.

En este caso, necesitará un Monitor de transacciones (servidor que admita el protocolo XA) y asegúrese de que sus bases de datos sean compatibles con XA también. La mayoría de (¿todos?) Los servidores J2EE vienen con Transaction Monitor incorporado. Si su código no se ejecuta en el servidor J2EE, entonces hay un montón de alternativas independientes: Atomicos, Bitronix, etc.

Puede probar Spring ChainedTransactionManager - http://docs.spring.io/spring-data/commons/docs/1.6.2.RELEASE/api/org/springframework/data/transaction/ChainedTransactionManager.html que Soporta transacciones de db distribuido. Esta podría ser una mejor alternativa a XA

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top