Definición
Session.startTransaction(<options>)Comienza una Transacción multidocumento asociada a la sesión. Puede tener como máximo una transacción abierta por sesión.
Cambiado en la 4.2 versión: A partir de MongoDB,4.2 las transacciones de múltiples documentos están disponibles tanto para clústeres fragmentados como para conjuntos de réplicas.
Importante
Dentro de una transacción, solo se pueden especificar operaciones de lectura y escritura (CRUD) en colecciones existentes. Por ejemplo, una transacción multidocumento no puede incluir una operación de inserción que genere una nueva colección.
El método puede tomar un documento con las siguientes
Session.startTransaction()opciones:{ readConcern: { level: <level>}, writeConcern: { w: <value>, j: <boolean>, wtimeout: <number> } } OpciónDescripciónreadConcernOpcional. Un documento que especifica el nivel de consistencia de lectura para todas las operaciones en la transacción, anulando el nivel de consistencia de lectura específico de la operación.
Puede especificar uno de los siguientes niveles de preocupación de lectura:
Para las consultas de lectura y, MongoDB a veces puede sustituir una consulta de lectura más
"local""majority"fuerte.writeConcernOpcional. Un documento que especifica la solicitud de escritura para la transacción. Esta solicitud de escritura se aplica a las operaciones de confirmación y cancelación de la transacción.
Las operaciones dentro de la transacción
"w: 1"utilizan, anulando la preocupación de escritura específica de la operación.Si se compromete utilizando la
"w: 1"preocupaciónde escritura, su transacción puede revertirse durante el proceso de conmutación por error.Para los controladores MongoDB, las transacciones utilizan la preocupación de escritura a nivel de cliente como predeterminada.
Compatibilidad
Este método está disponible en implementaciones alojadas en los siguientes entornos:
MongoDB Atlas: El servicio totalmente gestionado para implementaciones de MongoDB en la nube
MongoDB Enterprise: La versión basada en suscripción y autogestionada de MongoDB
MongoDB Community: La versión de MongoDB con código fuente disponible, de uso gratuito y autogestionada.
Comportamiento
Operaciones soportadas dentro de una transacción
Nota
Si se ejecuta con control de acceso, debe tener privilegios para las operaciones en la transacción.
Para transacciones multidocumento:
Puede crear colecciones e índices en transacciones. Para más información, consulte Crear colecciones e índices en una transacción.
Las colecciones utilizadas en una transacción pueden encontrarse en diferentes bases de datos.
Nota
No puedes crear nuevas colecciones en transacciones de escritura entre particiones. Por ejemplo, si guardas en una colección existente en una partición y creas implícitamente una colección en una partición diferente, MongoDB no puede realizar ambas operaciones en la misma transacción.
No se puede escribir en colecciones con tamaño fijo.
No puedes usar el nivel de consistencia de lectura
"snapshot"al leer de una colección con tamaño fijo. (A partir de MongoDB 5.0)No puedes leer ni escribir en colecciones en las bases de datos
config,adminolocal.No se puede escribir en las colecciones de
system.*.No puedes devolver el plan de query de las operaciones admitidas usando
explaino comandos similares.
Para los cursores creados fuera de una transacción, no puedes llamar a
getMoredentro de la transacción.Para los cursores creados en una transacción, no puedes llamar a
getMorefuera de la transacción.
No puede especificar el comando
killCursorscomo la primera operación en una transacción.Además, si ejecutas el comando
killCursorsdentro de una transacción, el servidor detiene inmediatamente los cursores especificados. No espera la confirmación de la transacción.
Método | Comando | Nota |
|---|---|---|
Excluyendo las siguientes etapas: | ||
Disponible en colecciones sin fragmentar. For sharded collections, use the aggregation pipeline with the
$group stage. See Distinct Operation. | ||
Si la operación de actualización o reemplazo se ejecuta con Para obtener más detalles, consulte Operaciones de administración. | ||
Si se ejecuta en una colección inexistente, la colección se crea implícitamente. Para obtener más detalles, consulte Operaciones de administración. | ||
Si se ejecuta en una colección inexistente, la colección se crea implícitamente. Para obtener más detalles, consulte Operaciones de administración. | ||
Si se ejecuta en una colección inexistente, la colección se crea implícitamente. Para obtener más detalles, consulte Operaciones de administración. |
Las operaciones que afectan al catálogo de la base de datos, como crear o eliminar una colección o un índice, no están permitidas en transacciones multidocumento. Por ejemplo, una transacción multidocumento no puede incluir una operación de inserción que dé como resultado la creación de una nueva colección.Consulte Operaciones restringidas.
Los comandos informativos, como hello, buildInfo, connectionStatus (y sus métodos asistentes) están permitidos en las transacciones; sin embargo, no pueden ser la primera operación de la transacción.
preferencia de lectura
primaryLas transaccionesadmiten preferencia de lectura.
Atomicidad
Mientras la transacción está abierta, ningún cambio de datos realizado por las operaciones en la transacción es visible fuera de la transacción:
Cuando se confirma una transacción, todos los cambios realizados en los datos se guardan y son visibles fuera de ella. Es decir, una transacción no confirmará algunos de sus cambios mientras revierte otros.
Hasta que se produzca la confirmación de una transacción, los cambios de datos realizados en la transacción no son visibles fuera de la transacción.
Sin embargo, cuando una transacción se guarda en múltiples fragmentos, no todas las operaciones de lectura externas necesitan esperar a que el resultado de la transacción confirmada sea visible en todos los fragmentos. Por ejemplo, si se confirma una transacción y la escritura 1 es visible en el fragmento A, pero la escritura 2 aún no es visible en el fragmento B, una lectura externa con el nivel de consistencia de lectura
"local"puede leer los resultados de la escritura 1 sin ver la escritura 2.Cuando una transacción se aborta, todos los cambios de datos realizados por las escrituras en la transacción se descartan sin que nunca sean visibles y la transacción termina.
Ejemplo
Imagine un escenario en el que, al realizar cambios en el registro de un empleado en la base de datos hr, desea asegurarse de que la colección events en la base de datos reporting esté sincronizada con los cambios hr. Es decir, desea asegurarse de que estas escrituras se realicen como una sola transacción, de modo que ambas operaciones se realicen correctamente o fallen.
La colección employees en la base de datos hr tiene los siguientes documentos:
{ "_id" : ObjectId("5af0776263426f87dd69319a"), "employee" : 3, "name" : { "title" : "Mr.", "name" : "Iba Ochs" }, "status" : "Active", "department" : "ABC" } { "_id" : ObjectId("5af0776263426f87dd693198"), "employee" : 1, "name" : { "title" : "Miss", "name" : "Ann Thrope" }, "status" : "Active", "department" : "ABC" } { "_id" : ObjectId("5af0776263426f87dd693199"), "employee" : 2, "name" : { "title" : "Mrs.", "name" : "Eppie Delta" }, "status" : "Active", "department" : "XYZ" }
La colección events en la base de datos reporting tiene los siguientes documentos:
{ "_id" : ObjectId("5af07daa051d92f02462644a"), "employee" : 1, "status" : { "new" : "Active", "old" : null }, "department" : { "new" : "ABC", "old" : null } } { "_id" : ObjectId("5af07daa051d92f02462644b"), "employee" : 2, "status" : { "new" : "Active", "old" : null }, "department" : { "new" : "XYZ", "old" : null } } { "_id" : ObjectId("5af07daa051d92f02462644c"), "employee" : 3, "status" : { "new" : "Active", "old" : null }, "department" : { "new" : "ABC", "old" : null } }
El siguiente ejemplo abre una transacción, actualiza el estado de un empleado a Inactive en el estado employees e inserta un documento correspondiente en la colección events y confirma las dos operaciones como una sola transacción.
// Runs the txnFunc and retries if TransientTransactionError encountered function runTransactionWithRetry(txnFunc, session) { while (true) { try { txnFunc(session); // performs transaction break; } catch (error) { // If transient error, retry the whole transaction if (error?.errorLabels?.includes("TransientTransactionError") ) { print("TransientTransactionError, retrying transaction ..."); continue; } else { throw error; } } } } // Retries commit if UnknownTransactionCommitResult encountered function commitWithRetry(session) { while (true) { try { session.commitTransaction(); // Uses write concern set at transaction start. print("Transaction committed."); break; } catch (error) { // Can retry commit if (error?.errorLabels?.includes("UnknownTransactionCommitResult") ) { print("UnknownTransactionCommitResult, retrying commit operation ..."); continue; } else { print("Error during commit ..."); throw error; } } } } // Updates two collections in a transactions function updateEmployeeInfo(session) { employeesCollection = session.getDatabase("hr").employees; eventsCollection = session.getDatabase("reporting").events; session.startTransaction( { readConcern: { level: "snapshot" }, writeConcern: { w: "majority" } } ); try{ employeesCollection.updateOne( { employee: 3 }, { $set: { status: "Inactive" } } ); eventsCollection.insertOne( { employee: 3, status: { new: "Inactive", old: "Active" } } ); } catch (error) { print("Caught exception during transaction, aborting."); session.abortTransaction(); throw error; } commitWithRetry(session); } // Start a session. session = db.getMongo().startSession( { readPreference: { mode: "primary" } } ); try{ runTransactionWithRetry(updateEmployeeInfo, session); } catch (error) { // Do something with error } finally { session.endSession(); }