Join us at MongoDB.local London on 7 May to unlock new possibilities for your data. Use WEB50 to save 50%.
Register now >
Docs Menu
Docs Home
/ /

Transacciones

En esta guía, puede aprender cómo usar el driver de Node.js para realizar transacciones. Las transacciones permiten ejecutar una serie de operaciones que no alteran ningún dato hasta que toda la transacción esté comprometida. Si alguna operación de la transacción falla, el controlador finaliza la transacción y descarta cualquier cambio en los datos antes de que se hagan visibles. Esta funcionalidad se llama atomicidad.

Como todas las operaciones de guardar en un solo documento en MongoDB son atómicas, es posible que desee utilizar transacciones para realizar un cambio atómico que modifique varios documentos. Esta situación requiere una transacción multi-documento. Las transacciones multi-documento son ACID compliant porque MongoDB garantiza que los datos involucrados en tus operaciones de transacción se mantengan coherentes, incluso si el driver encuentra errores inesperados.

Para obtener más información sobre el cumplimiento de ACID y las transacciones, consulte nuestra artículo sobre transacciones ACID.

Nota

Para ejecutar una transacción multi-documento, debes estar conectado a una implementación que ejecute MongoDB Server versión 4.0 o posterior.

Para obtener una lista detallada de limitaciones, consulta la sección Transacciones y operaciones en el manual de servidor.

Aprende más sobre cómo usar el driver para realizar transacciones multi-documento en las siguientes secciones de esta guía:

MongoDB habilita la coherencia causal en ciertas sesiones de clientes. El modelo de coherencia causal garantiza que en un sistema distribuido, las operaciones dentro de una sesión se ejecuten en un orden causal. Los clientes observan resultados que son coherentes con las relaciones causales, o las dependencias entre las operaciones. Por ejemplo, si realizas una serie de operaciones donde una depende lógicamente del resultado de otra, las lecturas subsecuentes reflejarán esa relación de dependencia.

Para garantizar la coherencia causal, las sesiones de los clientes deben cumplir los siguientes requisitos:

  • Al iniciar una sesión, el controlador debe habilitar la opción de consistencia causal. Esta opción está habilitada por defecto.

  • Las operaciones deben ejecutarse en una sola sesión en un solo hilo. De lo contrario, las sesiones o hilos deben comunicarse entre sí los valores de operation time y tiempo de clúster. Para ver un ejemplo de dos sesiones que comunican estos valores, consulte los Ejemplos de coherencia causal en el manual del servidor de MongoDB.

  • Debes utilizar un majority nivel de consistencia de lectura.

  • Debe usar un majority nivel de confirmación de escritura (write concern). Este es el valor predeterminado de nivel de confirmación de escritura (write concern).

La siguiente tabla describe las garantías que brindan las sesiones causalmente consistentes:

garantías
Descripción

Leer las escrituras

Las operaciones de lectura reflejan los resultados de las operaciones de escritura anteriores.

Lecturas monotónicas

Las operaciones de lectura no devuelven resultados que reflejen un estado de datos anterior al de una operación de lectura previa.

Escrituras monotónicas

Si una operación de escritura debe preceder a otras operaciones de escritura, el servidor ejecuta esta operación de escritura primero.

Por ejemplo, si llama a insertOne() para insertar un documento y luego llama a updateOne() para modificar el documento insertado, el servidor ejecuta primero la operación de inserción.

Las escrituras siguen a las lecturas

Si una operación de escritura debe seguir a otras operaciones de lectura, el servidor primero ejecuta las operaciones de lectura.

Por ejemplo, si llamas a findOne() para recuperar un documento y luego llamas a deleteOne() para borrar el documento recuperado, el servidor ejecutará primero la operación find.

Tip

Para aprender más sobre los conceptos mencionados en esta sección, consulta las siguientes entradas del manual del servidor MongoDB:

El controlador proporciona dos API para realizar transacciones: la API principal y la API de transacciones convenientes.

La Core API es un framework que te permite crear, confirmar y finalizar transacciones. Al utilizar esta API, debe realizar explícitamente las siguientes acciones:

  • Crea, confirma y finaliza la transacción.

  • Cree y finalice la sesión en la que se ejecute la transacción.

  • Implementar lógica de manejo de errores.

La API de transacciones conveniente es un marco que te permite realizar transacciones sin ser responsable de comprometerlas o finalizarlas. Esta API incorpora automáticamente lógica de manejo de errores para reintentar operaciones cuando el servidor muestra ciertos tipos de errores. Para obtener más información sobre este comportamiento, consulta la sección Errores de transacción de esta guía.

Importante

Cuando se conecta a MongoDB Server versión 4.2 o anterior, solo puede realizar operaciones de escritura en una transacción en colecciones que ya existen. Cuando se conecta a MongoDB Server versión 4.4 y posteriores, el servidor crea automáticamente colecciones según sea necesario cuando realiza operaciones de escritura en una transacción. Para obtener más información sobre este comportamiento, consulte Crear colecciones e índices en una transacción en el manual del servidor.

La API central proporciona los siguientes métodos para implementar transacciones:

Debes realizar los siguientes pasos cuando uses esta API:

  • Pasa la instancia de la sesión a cada operación que desees ejecutar en esa sesión.

  • Implemente un bloque catch en el que identifique los errores de transacción del servidor y la lógica de control de errores implementada.

El siguiente código demuestra cómo realizar una transacción utilizando la Core API:

async function coreTest(client) {
const session = client.startSession();
try {
session.startTransaction();
const savingsColl = client.db("bank").collection("savings_accounts");
await savingsColl.findOneAndUpdate(
{account_id: "9876"},
{$inc: {amount: -100 }},
{ session });
const checkingColl = client.db("bank").collection("checking_accounts");
await checkingColl.findOneAndUpdate(
{account_id: "9876"},
{$inc: {amount: 100 }},
{ session });
// ... perform other operations
await session.commitTransaction();
console.log("Transaction committed.");
} catch (error) {
console.log("An error occurred during the transaction:" + error);
await session.abortTransaction();
} finally {
await session.endSession();
}
}

Importante

Utilizar una sesión con el cliente que la inició

El controlador lanza un error si se proporciona una sesión de una instancia MongoClient a una instancia de cliente diferente.

Por ejemplo, el siguiente código genera un error MongoInvalidArgumentError porque crea una instancia ClientSession desde el cliente client1, pero proporciona esta sesión al cliente client2 para una operación de escritura:

const session = client1.startSession();
client2.db('myDB').collection('myColl').insertOne({ name: 'Jane Eyre' }, { session });

Tip

Gestión explícita de recursos

El controlador de Nodo.js admite de forma nativa la gestión explícita de recursos para MongoClient, ClientSession, ChangeStreams y cursores. Esta característica es experimental y está sujeta a cambios. Para aprender a utilizar la gestión explícita de recursos, consulta las Notas de versión v6.9.

Para ver un ejemplo completamente ejecutable que utiliza esta API, consulte Utilice el ejemplo de usode la API principal.

La API de Transacciones Convenientes ofrece los siguientes métodos para implementar transacciones:

  • withSession(): ejecuta la función de retorno que recibe dentro de una sesión. La API gestiona automáticamente la creación y finalización de la sesión.

  • withTransaction(): ejecuta la devolución de llamada que se le pasa dentro de una transacción y llama al commitTransaction() método cuando la devolución de llamada regresa.

Estos métodos devuelven el valor que devuelve la devolución de llamada. Por ejemplo, si una devolución de llamada que se pasa al método withTransaction() devuelve el documento { hello: "world" }, el método withTransaction() también lo devuelve.

Importante

Para evitar errores de bucle infinito, asegúrese de que la función de retorno que pase al método withTransaction() capture cualquier error que genere.

Cuando uses la API de Transacciones Convenientes, puedes propagar valores de retorno desde la función de retorno como los valores de retorno de los métodos withTransaction() y withSession() para trabajar con ellos en otras partes de tu código.

Debes realizar los siguientes pasos cuando uses esta API:

  • Pasa la instancia de la sesión a cada operación que desees ejecutar en esa sesión.

  • Implemente la sintaxis async await para cada operación en la sesión.

  • Evitar el paralelismo, como llamar al método Promise.all(). Utilizar sesiones en paralelo suele conducir a errores en el servidor.

El siguiente código demuestra cómo realizar una transacción utilizando la API de Transacciones Convenientes:

async function convTest(client) {
let txnRes = await client.withSession(async (session) =>
session.withTransaction(async (session) => {
const savingsColl = client.db("bank").collection("savings_accounts");
await savingsColl.findOneAndUpdate(
{account_id: "9876"},
{$inc: {amount: -100 }},
{ session });
const checkingColl = client.db("bank").collection("checking_accounts");
await checkingColl.findOneAndUpdate(
{account_id: "9876"},
{$inc: {amount: 100 }},
{ session });
// ... perform other operations
return "Transaction committed.";
}, null)
);
console.log(txnRes);
}

Para ver un ejemplo completamente ejecutable que utiliza esta API, consulte el ejemplo de uso de la API de transacciones convenientes.

Nota

Operaciones paralelas no admitidas

El driver de nodo.js no admite la ejecución de operaciones en paralelo dentro de una única transacción.

Puedes pasar una instancia TransactionOptions a los métodos startTransaction() y withTransaction() para configurar cómo ejecuta el driver una transacción. Cuando especifica una opción, sustituye el valor de la opción que podría haber configurado en su instancia de MongoClient.

La siguiente tabla incluye opciones que se pueden especificar en una instancia de TransactionOptions:

Configuración
Descripción

readConcern

Specifies read operation consistency of the replica set.
To learn more, see Read Concern in the Server manual.

writeConcern

Specifies the write operation level of acknowledgment required from a replica set.
To learn more, see Write Concern in the Server manual.

readPreference

Specifies how to route read operations to members of a replica set.
To learn more, see Read Preference in the Server manual.

maxCommitTimeMS

Especifica la duración que puede ejecutar la acción de commit en una transacción, en milisegundos.

Para obtener una lista completa de opciones, consulte la documentación de la API de TransactionOptions.

Nota

La transacción hereda los ajustes de tu instancia de MongoClient a menos que los especifica en las opciones de la transacción.

El siguiente código muestra cómo definir y pasar opciones de transacción al método startTransaction():

const txnOpts = {
readPreference: 'primary',
readConcern: { level: 'local' },
writeConcern: { w: 'majority' },
maxCommitTimeMS: 1000
};
session.startTransaction(txnOpts);

Debido a que las transacciones de MongoDB son compatibles con ACID, el driver podría producir errores durante la operación para garantizar que tus datos se mantengan coherentes. Si ocurren los siguientes errores, tu aplicación debe volver a intentar la transacción:

  • TransientTransactionError:: Se produce si una operación de escritura encuentra un error antes de que el controlador confirme la transacción. Para obtener más información sobre este tipo de error, consulte la descripción de TransientTransactionError en la página de la API de controladores en el manual del servidor.

  • UnknownTransactionCommitResult: Se lanza si la operación de confirmación encuentra un error. Para obtener más información sobre este tipo de error, consulta la descripción UnknownTransactionCommitResult en la página de controladores de la API en el manual del servidor.

Las siguientes secciones describen cómo gestionar estos errores al utilizar diferentes APIs.

La API de transacciones convenientes incorpora lógica de reintento para estos tipos de errores. El controlador reintenta automáticamente la transacción hasta que se produzca una confirmación exitosa.

Si está usando la Core API para realizar una transacción, debe añadir las siguientes funciones de gestión de errores a su aplicación:

  • Una función que vuelve a intentar toda la transacción cuando el conductor encuentra un TransientTransactionError

  • Una función que reintenta la operación de confirmación cuando el controlador encuentra un UnknownTransactionCommitResult

Estas funciones deben ejecutarse hasta que se realice un compromiso exitoso o se produzca un error diferente. Para un ejemplo de esta lógica de reintentos, consulta la sección de la Core API en la página de la API de controladores del manual del servidor.

Volver

Operaciones compuestas

En esta página