Volver al inicio

Transacciones multi-fase: implementación de operaciones tolerantes a fallos en DBMS

El artículo explica la implementación de transacciones multi-fase usando operaciones idempotentes para garantizar la tolerancia a fallos en DBMS. Se consideran las etapas de bloqueo, ejecución y desbloqueo con ejemplos de código para MongoDB.

Cómo implementar transacciones tolerantes a fallos: desglose paso a paso
Advertisement 728x90

Transacciones Resilientes: Operaciones Idempotentes en la Práctica

Las transacciones multifase garantizan la integridad de los datos durante fallos mediante operaciones idempotentes y un registro de estados. Este enfoque funciona con cualquier base de datos, incluida MongoDB, y previene pérdidas de datos por cortes de energía o caídas del sistema.

Cómo Funcionan las Transacciones Multifase

Las transacciones se dividen en etapas secuenciales, cada una registrada en una tabla TRANSACTIONS separada. Estados clave:

  • blocking — bloqueo de cuentas para evitar operaciones concurrentes.
  • save_balance — captura de saldos originales en el registro.
  • main — ejecución de la transferencia principal de fondos.
  • unlock — liberación de bloqueos de cuentas tras completarse.
  • finished — estado final para transacciones exitosas.

La idempotencia asegura que repetir una etapa tras un fallo no corrompa los datos. Por ejemplo, A := B + 1 es idempotente, mientras que A := A + 1 no lo es, pero se puede dividir en dos pasos idempotentes.

Google AdInline article slot

Pasos de Implementación con Ejemplos de Código

Transfiramos $5 de la cuenta de Assange a la de Agent Y. Datos iniciales en la tabla ACCOUNTS:

| ID | NAME | BALANCE | TR_ID |

|----|----------|---------|-------|

Google AdInline article slot

| 34 | Assange | 300 | null |

| 78 | Agent Y | 7 | null |

1. Bloquear Cuentas (STATUS='blocking')

Primero, crea un registro en TRANSACTIONS:

Google AdInline article slot

| ID | FROM_ID | TO_ID | AMOUNT | FROM_BALANCE | TO_BALANCE | STATUS |

|----|---------|-------|--------|--------------|------------|----------|

| 172| 34 | 78 | 250 | null | null | blocking |

El bloqueo usa comandos atómicos, por ejemplo en MongoDB:

db.accounts.updateOne(
  { ID: 34, TR_ID: null },
  { $set: { TR_ID: 172 } }
);

Si no se actualiza ningún documento, el bloqueo falló: reintenta o aborta. Ordena los ID previamente para evitar interbloqueos.

2. Capturar Saldos (STATUS='save_balance')

Tras el bloqueo, copia los saldos originales a TRANSACTIONS — idempotente por diseño:

db.transactions.updateOne(
  { ID: 172 },
  { $set: { FROM_BALANCE: 300, TO_BALANCE: 7, STATUS: 'save_balance' } }
);

3. Ejecutar Transferencia (STATUS='main')

La operación principal usa los saldos guardados para idempotencia:

db.accounts.updateOne(
  { ID: 34, TR_ID: 172 },
  { $set: { BALANCE: 50 } } // 300 - 250
);

db.accounts.updateOne(
  { ID: 78, TR_ID: 172 },
  { $set: { BALANCE: 257 } } // 7 + 250
);

Actualiza el estado a 'unlock' solo tras aplicar los cambios.

4. Desbloquear y Finalizar (STATUS='unlock')

Libera los bloqueos verificando TR_ID:

db.accounts.updateOne(
  { ID: 34, TR_ID: 172 },
  { $set: { TR_ID: null } }
);

Tras desbloquear ambas, establece el estado en 'finished'.

Ventajas y Limitaciones

Ventajas clave:

  • Tolerancia a fallos: Se recupera de cualquier fallo sin pérdida de datos.
  • Idempotencia: Permite reintentar operaciones de forma segura, esencial en sistemas distribuidos.
  • Versatilidad: Funciona en cualquier base de datos, no solo MongoDB.
  • Consistencia: Mantiene la integridad en cada etapa.
  • Rendimiento: El registro extra puede ralentizar un poco.

Desventajas: mayor complejidad y sobrecarga de journaling. Para apps financieras o sistemas críticos, vale la pena.

Consejos para Desarrolladores

  • Aprovecha las operaciones atómicas de tu BD para bloqueos y actualizaciones.
  • Implementa lógica de reintentos para bloqueos fallidos.
  • Prueba escenarios de caídas, como procesos terminados abruptamente.
  • Ordena los ID para reducir riesgos de interbloqueo.

Esto ofrece fiabilidad nivel 2PC con la flexibilidad de NoSQL.

— Editorial Team

Advertisement 728x90

Leer después