Introducción a las Transacciones en MongoDB

Las transacciones en MongoDB permiten realizar múltiples operaciones de lectura y escritura en múltiples documentos (y colecciones) de manera atómica. Esto significa que todas las operaciones dentro de una transacción se completan con éxito o ninguna de ellas se aplica, garantizando la consistencia de los datos.

Conceptos Clave

  • Atomicidad: Todas las operaciones dentro de una transacción se completan o ninguna de ellas se aplica.
  • Consistencia: Los datos permanecen en un estado consistente antes y después de la transacción.
  • Aislamiento: Las transacciones se ejecutan de manera aislada, sin interferir entre sí.
  • Durabilidad: Una vez que una transacción se ha confirmado, los cambios son permanentes.

Requisitos Previos

Antes de comenzar a trabajar con transacciones en MongoDB, asegúrate de tener:

  1. MongoDB 4.0 o superior: Las transacciones multi-documento están disponibles a partir de MongoDB 4.0.
  2. Replica Set: Las transacciones requieren un conjunto de réplicas (replica set) para funcionar.

Sintaxis Básica de las Transacciones

Iniciar una Transacción

Para iniciar una transacción, primero debes iniciar una sesión. Luego, puedes comenzar la transacción dentro de esa sesión.

const session = client.startSession();
session.startTransaction();

Realizar Operaciones dentro de una Transacción

Puedes realizar cualquier operación de lectura o escritura dentro de una transacción. Aquí hay un ejemplo de cómo insertar documentos en dos colecciones diferentes dentro de una transacción:

const session = client.startSession();
session.startTransaction();

try {
    const usersCollection = client.db("mydatabase").collection("users");
    const ordersCollection = client.db("mydatabase").collection("orders");

    await usersCollection.insertOne({ name: "John Doe" }, { session });
    await ordersCollection.insertOne({ item: "Laptop", quantity: 1 }, { session });

    await session.commitTransaction();
    console.log("Transaction committed.");
} catch (error) {
    await session.abortTransaction();
    console.error("Transaction aborted due to an error: ", error);
} finally {
    session.endSession();
}

Confirmar una Transacción

Para confirmar una transacción, utiliza el método commitTransaction():

await session.commitTransaction();

Abortar una Transacción

Si ocurre un error o deseas revertir las operaciones, puedes abortar la transacción utilizando el método abortTransaction():

await session.abortTransaction();

Ejemplo Completo

A continuación, se muestra un ejemplo completo de cómo usar transacciones en MongoDB:

const { MongoClient } = require('mongodb');

async function run() {
    const uri = "your_mongodb_connection_string";
    const client = new MongoClient(uri, { useNewUrlParser: true, useUnifiedTopology: true });

    try {
        await client.connect();
        const session = client.startSession();
        session.startTransaction();

        try {
            const usersCollection = client.db("mydatabase").collection("users");
            const ordersCollection = client.db("mydatabase").collection("orders");

            await usersCollection.insertOne({ name: "John Doe" }, { session });
            await ordersCollection.insertOne({ item: "Laptop", quantity: 1 }, { session });

            await session.commitTransaction();
            console.log("Transaction committed.");
        } catch (error) {
            await session.abortTransaction();
            console.error("Transaction aborted due to an error: ", error);
        } finally {
            session.endSession();
        }
    } finally {
        await client.close();
    }
}

run().catch(console.dir);

Ejercicio Práctico

Ejercicio

  1. Objetivo: Implementar una transacción que inserte un nuevo usuario y un nuevo pedido en una base de datos MongoDB.
  2. Requisitos:
    • Crear una base de datos llamada shop.
    • Crear dos colecciones: customers y purchases.
    • Insertar un documento en cada colección dentro de una transacción.

Solución

const { MongoClient } = require('mongodb');

async function run() {
    const uri = "your_mongodb_connection_string";
    const client = new MongoClient(uri, { useNewUrlParser: true, useUnifiedTopology: true });

    try {
        await client.connect();
        const session = client.startSession();
        session.startTransaction();

        try {
            const customersCollection = client.db("shop").collection("customers");
            const purchasesCollection = client.db("shop").collection("purchases");

            await customersCollection.insertOne({ name: "Alice" }, { session });
            await purchasesCollection.insertOne({ item: "Smartphone", quantity: 1 }, { session });

            await session.commitTransaction();
            console.log("Transaction committed.");
        } catch (error) {
            await session.abortTransaction();
            console.error("Transaction aborted due to an error: ", error);
        } finally {
            session.endSession();
        }
    } finally {
        await client.close();
    }
}

run().catch(console.dir);

Errores Comunes y Consejos

  • Error: "Transaction numbers are only allowed on a replica set member or mongos": Asegúrate de que tu MongoDB está configurado como un conjunto de réplicas.
  • Error: "WriteConflict": Esto puede ocurrir si dos transacciones intentan modificar el mismo documento al mismo tiempo. Intenta reintentar la transacción.
  • Consejo: Siempre maneja las excepciones y asegúrate de abortar la transacción en caso de error para evitar inconsistencias en los datos.

Conclusión

Las transacciones en MongoDB proporcionan una manera poderosa de garantizar la consistencia y la integridad de los datos en operaciones complejas. Con la capacidad de realizar múltiples operaciones de lectura y escritura de manera atómica, puedes construir aplicaciones más robustas y confiables. En el siguiente módulo, exploraremos cómo MongoDB maneja la replicación para mejorar la disponibilidad y la durabilidad de los datos.

© Copyright 2024. Todos los derechos reservados