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.

Dado que todas las operaciones de escritura en un solo documento en MongoDB son atómicas, podría ser útil usar transacciones para realizar un cambio atómico que modifique varios documentos. Esta situación requiere una transacción multidocumento. Las transacciones multidocumento cumplen con ACID porque MongoDB garantiza que los datos involucrados en las operaciones de transacción se mantengan consistentes, incluso si el controlador encuentra errores inesperados.

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

Nota

Para ejecutar una transacción de múltiples documentos, debe 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 permite la consistencia causal en ciertas sesiones de cliente. El modelo de consistencia causal garantiza que, en un sistema distribuido, las operaciones dentro de una sesión se ejecuten en un orden causal. Los clientes observan resultados consistentes con las relaciones causales o las dependencias entre operaciones. Por ejemplo, si se realiza una serie de operaciones donde una depende lógicamente del resultado de otra, las lecturas posteriores reflejan la 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 subproceso. De lo contrario, las sesiones o subprocesos deben comunicarse entre sí los valores de tiempo de la operación y del clúster. Para ver un ejemplo de dos sesiones que comunican estos valores, consulte los ejemplos de consistencia causal en el manual de MongoDB Server.

  • Debes utilizar un majority leer preocupación.

  • 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ía
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 anterior.

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 ejecuta primero las operaciones de lectura.

Por ejemplo, si llama a findOne() para recuperar un documento y luego llama a deleteOne() para eliminar el documento recuperado, el servidor ejecuta primero la operación de búsqueda.

Tip

Para obtener más información sobre los conceptos mencionados en esta sección, consulte las siguientes entradas del manual de MongoDB Server:

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

La API principal es un marco que permite crear, confirmar y finalizar transacciones. Al usar esta API, debe realizar explícitamente las siguientes acciones:

  • Crear, confirmar y finalizar la transacción.

  • Crea y finaliza la sesión en la que ejecutas la transacción.

  • Implementar lógica de manejo de errores.

La API de Transacciones Convenientes es un marco que permite realizar transacciones sin tener que confirmarlas ni finalizarlas. Esta API incorpora automáticamente lógica de gestión de errores para reintentar operaciones cuando el servidor genera ciertos tipos de error. Para obtener más información sobre este comportamiento, consulte la sección "Errores de Transacción" de esta guía.

Importante

Al conectarse a MongoDB Server (versión 4.2 o anterior), solo se pueden realizar operaciones de escritura en una transacción en colecciones ya existentes. Al conectarse a MongoDB Server (versión o 4.4 posterior), el servidor crea automáticamente colecciones según sea necesario al realizar 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 principal proporciona los siguientes métodos para implementar transacciones:

Debes realizar los siguientes pasos al utilizar esta API:

  • Pase la instancia de sesión a cada operación que desee ejecutar en esa sesión.

  • Implemente un bloque catch en el que identifique errores de transacciones del servidor e implemente la lógica de manejo de errores.

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

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

Utilice 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 proporciona los siguientes métodos para implementar transacciones:

  • withSession(): ejecuta la devolución de llamada que se le pasa dentro de una sesión. La API gestiona la creación y finalización de la sesión automáticamente.

  • 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 devolución de llamada que pase al método withTransaction() detecte cualquier error que genere.

Cuando utiliza la API de transacciones convenientes, puede propagar valores de retorno de la devolución de llamada como valores de retorno de los métodos withTransaction() y withSession() para trabajar con ellos en otras partes de su código.

Debes realizar los siguientes pasos al utilizar esta API:

  • Pase la instancia de sesión a cada operación que desee ejecutar en esa sesión.

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

  • Evite el paralelismo, como llamar al método Promise.all(). Usar sesiones en paralelo suele provocar errores del servidor.

El siguiente código demuestra cómo realizar una transacción mediante 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.

Puede pasar una instancia TransactionOptions a los métodos startTransaction() y withTransaction() para configurar cómo el controlador realiza una transacción. Al especificar una opción, esta anula el valor de la opción que haya configurado en su instancia MongoClient.

La siguiente tabla incluye opciones que puede especificar en una instancia 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 el tiempo que puede ejecutarse una acción de confirmación 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 las configuraciones de su instancia MongoClient a menos que las especifique en sus opciones de 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);

Dado que las transacciones de MongoDB cumplen con ACID, el controlador podría generar errores durante la operación para garantizar la coherencia de los datos. Si se producen los siguientes errores, la aplicación debe reintentar la transacción:

  • TransientTransactionError: Se genera 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 del manual del servidor.

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

Las siguientes secciones describen cómo manejar estos errores al utilizar diferentes API.

La API de Transacciones Convenientes incorpora lógica de reintento para estos tipos de error. El controlador reintenta automáticamente la transacción hasta que se confirma correctamente.

Si está utilizando la API principal para realizar una transacción, debe agregar las siguientes funciones de manejo 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 vuelve a intentar la operación de confirmación cuando el controlador encuentra un UnknownTransactionCommitResult

Estas funciones deben ejecutarse hasta que se confirme correctamente o se produzca un error diferente. Para ver un ejemplo de esta lógica de reintento, consulte la sección API principal en la página API de controladores del manual del servidor.

Volver

Operaciones compuestas

En esta página