Docs Menu
Docs Home
/
Manual de base de datos

Transacciones

En MongoDB, una operación en un solo documento es atómica. Debido a que puede usar documentos incrustados y arreglos para capturar las relaciones entre los datos en una estructura de un solo documento en lugar de normalizar en varios documentos y colecciones, esta atomicidad de un solo documento elimina la necesidad de transacciones distribuidas para muchos casos de uso práctico.

Para situaciones que requieren la atomicidad de las lecturas y escrituras en varios documentos (ya sea en una sola colección o en varias), MongoDB admite transacciones distribuidas. Con las transacciones distribuidas, se pueden utilizar en múltiples operaciones, colecciones, bases de datos, documentos y fragmentos.

La información de esta página se aplica a las 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.


➤ Use el menú desplegable Seleccione su idioma en la parte superior derecha para establecer el idioma del siguiente ejemplo.


Este ejemplo resalta los componentes clave de la API de transacciones. En particular, utiliza la API de función de retorno. La API de función de retorno:

  • inicia una transacción

  • ejecuta las operaciones especificadas

  • confirma el resultado o finaliza la transacción en caso de error

Errores en las operaciones del lado del servidor, como el DuplicateKeyErrorPuede finalizar la transacción y generar un error de comando para alertar al usuario de su finalización. Este comportamiento es previsible y ocurre incluso si el cliente nunca llama Session.abortTransaction() a. Para incorporar un manejo de errores personalizado, utilice la API principal en su transacción.

La callback API incorpora lógica de reintento para ciertos errores. El controlador intenta volver a ejecutar la transacción después de un TransientTransactionError o un error de confirmación UnknownTransactionCommitResult.

A partir de MongoDB,6.0.5 el servidor no vuelve a intentar la transacción si recibe un error TransactionTooLargeForCache.

A partir de MongoDB 8.1, si una operación upsert se ejecuta en una transacción de múltiples documentos, entonces upsert no vuelve a intentarlo cuando encuentra un error de clave duplicada.

Importante

static bool
with_transaction_example(bson_error_t *error)
{
mongoc_client_t *client = NULL;
mongoc_write_concern_t *wc = NULL;
mongoc_collection_t *coll = NULL;
bool success = false;
bool ret = false;
bson_t *doc = NULL;
bson_t *insert_opts = NULL;
mongoc_client_session_t *session = NULL;
mongoc_transaction_opt_t *txn_opts = NULL;
/* For a replica set, include the replica set name and a seedlist of the
* members in the URI string; e.g.
* uri_repl = "mongodb://mongodb0.example.com:27017,mongodb1.example.com:" \
* "27017/?replicaSet=myRepl";
* client = mongoc_client_new (uri_repl);
* For a sharded cluster, connect to the mongos instances; e.g.
* uri_sharded =
* "mongodb://mongos0.example.com:27017,mongos1.example.com:27017/";
* client = mongoc_client_new (uri_sharded);
*/
client = get_client();
/* Prereq: Create collections. Note Atlas connection strings include a majority write
* concern by default.
*/
wc = mongoc_write_concern_new();
mongoc_write_concern_set_wmajority(wc, 1000);
insert_opts = bson_new();
mongoc_write_concern_append(wc, insert_opts);
coll = mongoc_client_get_collection(client, "mydb1", "foo");
doc = BCON_NEW("abc", BCON_INT32(0));
ret = mongoc_collection_insert_one(coll, doc, insert_opts, NULL /* reply */, error);
if (!ret) {
goto fail;
}
bson_destroy(doc);
mongoc_collection_destroy(coll);
coll = mongoc_client_get_collection(client, "mydb2", "bar");
doc = BCON_NEW("xyz", BCON_INT32(0));
ret = mongoc_collection_insert_one(coll, doc, insert_opts, NULL /* reply */, error);
if (!ret) {
goto fail;
}
/* Step 1: Start a client session. */
session = mongoc_client_start_session(client, NULL /* opts */, error);
if (!session) {
goto fail;
}
/* Step 2: Optional. Define options to use for the transaction. */
txn_opts = mongoc_transaction_opts_new();
mongoc_transaction_opts_set_write_concern(txn_opts, wc);
/* Step 3: Use mongoc_client_session_with_transaction to start a transaction,
* execute the callback, and commit (or abort on error). */
ret = mongoc_client_session_with_transaction(session, callback, txn_opts, NULL /* ctx */, NULL /* reply */, error);
if (!ret) {
goto fail;
}
success = true;
fail:
bson_destroy(doc);
mongoc_collection_destroy(coll);
bson_destroy(insert_opts);
mongoc_write_concern_destroy(wc);
mongoc_transaction_opts_destroy(txn_opts);
mongoc_client_session_destroy(session);
mongoc_client_destroy(client);
return success;
}
/* Define the callback that specifies the sequence of operations to perform
* inside the transactions. */
static bool
callback(mongoc_client_session_t *session, void *ctx, bson_t **reply, bson_error_t *error)
{
mongoc_client_t *client = NULL;
mongoc_collection_t *coll = NULL;
bson_t *doc = NULL;
bson_t *opts = bson_new();
bool success = false;
bool ret = false;
BSON_UNUSED(ctx);
BSON_UNUSED(reply);
// Important:: The logical session ID MUST be applied to all associated operations.
ret = mongoc_client_session_append(session, opts, error);
if (!ret) {
goto fail;
}
client = mongoc_client_session_get_client(session);
coll = mongoc_client_get_collection(client, "mydb1", "foo");
doc = BCON_NEW("abc", BCON_INT32(1));
ret = mongoc_collection_insert_one(coll, doc, opts, NULL, error);
if (!ret) {
goto fail;
}
bson_destroy(doc);
mongoc_collection_destroy(coll);
coll = mongoc_client_get_collection(client, "mydb2", "bar");
doc = BCON_NEW("xyz", BCON_INT32(999));
ret = mongoc_collection_insert_one(coll, doc, opts, NULL, error);
if (!ret) {
goto fail;
}
success = true;
fail:
mongoc_collection_destroy(coll);
bson_destroy(opts);
bson_destroy(doc);
return success;
}

Este ejemplo resalta los componentes clave de la API de transacciones. En particular, utiliza la API de función de retorno. La API de función de retorno:

  • inicia una transacción

  • ejecuta las operaciones especificadas

  • confirma el resultado o finaliza la transacción en caso de error

Los errores en las operaciones del lado del servidor, como el DuplicateKeyError, pueden finalizar la transacción y producir un error de comando para alertar al usuario de que la transacción ha terminado. Este comportamiento es esperado y ocurre incluso si el cliente nunca llama a Session.abortTransaction(). Para incorporar una gestión personalizada de errores, se debe usar la Core API en la transacción.

La callback API incorpora lógica de reintento para ciertos errores. El controlador intenta volver a ejecutar la transacción después de un TransientTransactionError o un error de confirmación UnknownTransactionCommitResult.

A partir de MongoDB,6.0.5 el servidor no vuelve a intentar la transacción si recibe un error TransactionTooLargeForCache.

A partir de MongoDB 8.1, si una operación upsert se ejecuta en una transacción de múltiples documentos, entonces upsert no vuelve a intentarlo cuando encuentra un error de clave duplicada.

Importante

// The mongocxx::instance constructor and destructor initialize and shut down the driver,
// respectively. Therefore, a mongocxx::instance must be created before using the driver and
// must remain alive for as long as the driver is in use.
mongocxx::instance inst{};
// For a replica set, include the replica set name and a seedlist of the members in the URI
// string; e.g.
// uriString =
// 'mongodb://mongodb0.example.com:27017,mongodb1.example.com:27017/?replicaSet=myRepl'
// For a sharded cluster, connect to the mongos instances; e.g.
// uriString = 'mongodb://mongos0.example.com:27017,mongos1.example.com:27017/'
mongocxx::client client{mongocxx::uri{}};
// Prepare to set majority write explicitly. Note: on Atlas deployments this won't always be
// needed. The suggested Atlas connection string includes majority write concern by default.
write_concern wc_majority{};
wc_majority.acknowledge_level(write_concern::level::k_majority);
// Prereq: Create collections.
auto foo = client["mydb1"]["foo"];
auto bar = client["mydb2"]["bar"];
try {
options::insert opts;
opts.write_concern(wc_majority);
foo.insert_one(make_document(kvp("abc", 0)), opts);
bar.insert_one(make_document(kvp("xyz", 0)), opts);
} catch (mongocxx::exception const& e) {
std::cout << "An exception occurred while inserting: " << e.what() << std::endl;
return EXIT_FAILURE;
}
// Step 1: Define the callback that specifies the sequence of operations to perform inside the
// transactions.
client_session::with_transaction_cb callback = [&](client_session* session) {
// Important:: You must pass the session to the operations.
foo.insert_one(*session, make_document(kvp("abc", 1)));
bar.insert_one(*session, make_document(kvp("xyz", 999)));
};
// Step 2: Start a client session
auto session = client.start_session();
// Step 3: Use with_transaction to start a transaction, execute the callback,
// and commit (or abort on error).
try {
options::transaction opts;
opts.write_concern(wc_majority);
session.with_transaction(callback, opts);
} catch (mongocxx::exception const& e) {
std::cout << "An exception occurred: " << e.what() << std::endl;
return EXIT_FAILURE;
}
return EXIT_SUCCESS;

Este ejemplo resalta los componentes clave de la API de transacciones. En particular, utiliza la API de función de retorno. La API de función de retorno:

  • inicia una transacción

  • ejecuta las operaciones especificadas

  • confirma el resultado o finaliza la transacción en caso de error

Los errores en las operaciones del lado del servidor, como el DuplicateKeyError, pueden finalizar la transacción y producir un error de comando para alertar al usuario de que la transacción ha terminado. Este comportamiento es esperado y ocurre incluso si el cliente nunca llama a Session.abortTransaction(). Para incorporar una gestión personalizada de errores, se debe usar la Core API en la transacción.

La callback API incorpora lógica de reintento para ciertos errores. El controlador intenta volver a ejecutar la transacción después de un TransientTransactionError o un error de confirmación UnknownTransactionCommitResult.

A partir de MongoDB,6.0.5 el servidor no vuelve a intentar la transacción si recibe un error TransactionTooLargeForCache.

A partir de MongoDB 8.1, si una operación upsert se ejecuta en una transacción de múltiples documentos, entonces upsert no vuelve a intentarlo cuando encuentra un error de clave duplicada.

Importante

// For a replica set, include the replica set name and a seedlist of the members in the URI string; e.g.
// string uri = "mongodb://mongodb0.example.com:27017,mongodb1.example.com:27017/?replicaSet=myRepl";
// For a sharded cluster, connect to the mongos instances; e.g.
// string uri = "mongodb://mongos0.example.com:27017,mongos1.example.com:27017/";
var client = new MongoClient(connectionString);
// Prereq: Create collections.
var database1 = client.GetDatabase("mydb1");
var collection1 = database1.GetCollection<BsonDocument>("foo").WithWriteConcern(WriteConcern.WMajority);
collection1.InsertOne(new BsonDocument("abc", 0));
var database2 = client.GetDatabase("mydb2");
var collection2 = database2.GetCollection<BsonDocument>("bar").WithWriteConcern(WriteConcern.WMajority);
collection2.InsertOne(new BsonDocument("xyz", 0));
// Step 1: Start a client session.
using (var session = client.StartSession())
{
// Step 2: Optional. Define options to use for the transaction.
var transactionOptions = new TransactionOptions(
writeConcern: WriteConcern.WMajority);
// Step 3: Define the sequence of operations to perform inside the transactions
var cancellationToken = CancellationToken.None; // normally a real token would be used
result = session.WithTransaction(
(s, ct) =>
{
try
{
collection1.InsertOne(s, new BsonDocument("abc", 1), cancellationToken: ct);
collection2.InsertOne(s, new BsonDocument("xyz", 999), cancellationToken: ct);
}
catch (MongoWriteException)
{
// Do something in response to the exception
throw; // NOTE: You must rethrow the exception otherwise an infinite loop can occur.
}
return "Inserted into collections in different databases";
},
transactionOptions,
cancellationToken);
}

Este ejemplo resalta los componentes clave de la API de transacciones. En particular, utiliza la API de función de retorno. La API de función de retorno:

  • inicia una transacción

  • ejecuta las operaciones especificadas

  • confirma el resultado o finaliza la transacción en caso de error

Los errores en las operaciones del lado del servidor, como el DuplicateKeyError, pueden finalizar la transacción y producir un error de comando para alertar al usuario de que la transacción ha terminado. Este comportamiento es esperado y ocurre incluso si el cliente nunca llama a Session.abortTransaction(). Para incorporar una gestión personalizada de errores, se debe usar la Core API en la transacción.

La callback API incorpora lógica de reintento para ciertos errores. El controlador intenta volver a ejecutar la transacción después de un TransientTransactionError o un error de confirmación UnknownTransactionCommitResult.

A partir de MongoDB,6.0.5 el servidor no vuelve a intentar la transacción si recibe un error TransactionTooLargeForCache.

A partir de MongoDB 8.1, si una operación upsert se ejecuta en una transacción de múltiples documentos, entonces upsert no vuelve a intentarlo cuando encuentra un error de clave duplicada.

Importante

// WithTransactionExample is an example of using the Session.WithTransaction function.
func WithTransactionExample(ctx context.Context) error {
// For a replica set, include the replica set name and a seedlist of the members in the URI string; e.g.
// uri := "mongodb://mongodb0.example.com:27017,mongodb1.example.com:27017/?replicaSet=myRepl"
// For a sharded cluster, connect to the mongos instances; e.g.
// uri := "mongodb://mongos0.example.com:27017,mongos1.example.com:27017/"
uri := mtest.ClusterURI()
clientOpts := options.Client().ApplyURI(uri)
client, err := mongo.Connect(clientOpts)
if err != nil {
return err
}
defer func() { _ = client.Disconnect(ctx) }()
// Prereq: Create collections.
wcMajority := writeconcern.Majority()
wcMajorityCollectionOpts := options.Collection().SetWriteConcern(wcMajority)
fooColl := client.Database("mydb1").Collection("foo", wcMajorityCollectionOpts)
barColl := client.Database("mydb1").Collection("bar", wcMajorityCollectionOpts)
// Step 1: Define the callback that specifies the sequence of operations to perform inside the transaction.
callback := func(sesctx context.Context) (any, error) {
// Important: You must pass sesctx as the Context parameter to the operations for them to be executed in the
// transaction.
if _, err := fooColl.InsertOne(sesctx, bson.D{{"abc", 1}}); err != nil {
return nil, err
}
if _, err := barColl.InsertOne(sesctx, bson.D{{"xyz", 999}}); err != nil {
return nil, err
}
return nil, nil
}
// Step 2: Start a session and run the callback using WithTransaction.
session, err := client.StartSession()
if err != nil {
return err
}
defer session.EndSession(ctx)
result, err := session.WithTransaction(ctx, callback)
if err != nil {
return err
}
log.Printf("result: %v\n", result)
return nil
}

Este ejemplo resalta los componentes clave de la API de transacciones. En particular, utiliza la API de función de retorno. La API de función de retorno:

  • inicia una transacción

  • ejecuta las operaciones especificadas

  • confirma el resultado o finaliza la transacción en caso de error

Los errores en las operaciones del lado del servidor, como el DuplicateKeyError, pueden finalizar la transacción y producir un error de comando para alertar al usuario de que la transacción ha terminado. Este comportamiento es esperado y ocurre incluso si el cliente nunca llama a Session.abortTransaction(). Para incorporar una gestión personalizada de errores, se debe usar la Core API en la transacción.

La callback API incorpora lógica de reintento para ciertos errores. El controlador intenta volver a ejecutar la transacción después de un TransientTransactionError o un error de confirmación UnknownTransactionCommitResult.

A partir de MongoDB,6.0.5 el servidor no vuelve a intentar la transacción si recibe un error TransactionTooLargeForCache.

A partir de MongoDB 8.1, si una operación upsert se ejecuta en una transacción de múltiples documentos, entonces upsert no vuelve a intentarlo cuando encuentra un error de clave duplicada.

Importante

/*
For a replica set, include the replica set name and a seedlist of the members in the URI string; e.g.
String uri = "mongodb://mongodb0.example.com:27017,mongodb1.example.com:27017/admin?replicaSet=myRepl";
For a sharded cluster, connect to the mongos instances.
For example:
String uri = "mongodb://mongos0.example.com:27017,mongos1.example.com:27017:27017/admin";
*/
final MongoClient client = MongoClients.create(uri);
/*
Create collections.
*/
client.getDatabase("mydb1").getCollection("foo")
.withWriteConcern(WriteConcern.MAJORITY).insertOne(new Document("abc", 0));
client.getDatabase("mydb2").getCollection("bar")
.withWriteConcern(WriteConcern.MAJORITY).insertOne(new Document("xyz", 0));
/* Step 1: Start a client session. */
final ClientSession clientSession = client.startSession();
/* Step 2: Optional. Define options to use for the transaction. */
TransactionOptions txnOptions = TransactionOptions.builder()
.writeConcern(WriteConcern.MAJORITY)
.build();
/* Step 3: Define the sequence of operations to perform inside the transactions. */
TransactionBody txnBody = new TransactionBody<String>() {
public String execute() {
MongoCollection<Document> coll1 = client.getDatabase("mydb1").getCollection("foo");
MongoCollection<Document> coll2 = client.getDatabase("mydb2").getCollection("bar");
/*
Important:: You must pass the session to the operations.
*/
coll1.insertOne(clientSession, new Document("abc", 1));
coll2.insertOne(clientSession, new Document("xyz", 999));
return "Inserted into collections in different databases";
}
};
try {
/*
Step 4: Use .withTransaction() to start a transaction,
execute the callback, and commit (or abort on error).
*/
clientSession.withTransaction(txnBody, txnOptions);
} catch (RuntimeException e) {
// some error handling
} finally {
clientSession.close();
}

Este ejemplo resalta los componentes clave de la API de transacciones. En particular, utiliza la API de función de retorno. La API de función de retorno:

  • inicia una transacción

  • ejecuta las operaciones especificadas

  • confirma el resultado o finaliza la transacción en caso de error

Los errores en las operaciones del lado del servidor, como el DuplicateKeyError, pueden finalizar la transacción y producir un error de comando para alertar al usuario de que la transacción ha terminado. Este comportamiento es esperado y ocurre incluso si el cliente nunca llama a Session.abortTransaction(). Para incorporar una gestión personalizada de errores, se debe usar la Core API en la transacción.

La callback API incorpora lógica de reintento para ciertos errores. El controlador intenta volver a ejecutar la transacción después de un TransientTransactionError o un error de confirmación UnknownTransactionCommitResult.

A partir de MongoDB,6.0.5 el servidor no vuelve a intentar la transacción si recibe un error TransactionTooLargeForCache.

A partir de MongoDB 8.1, si una operación upsert se ejecuta en una transacción de múltiples documentos, entonces upsert no vuelve a intentarlo cuando encuentra un error de clave duplicada.

Importante

# For a replica set, include the replica set name and a seedlist of the members in the URI string; e.g.
# uriString = 'mongodb://mongodb0.example.com:27017,mongodb1.example.com:27017/?replicaSet=myRepl'
# For a sharded cluster, connect to the mongos instances; e.g.
# uriString = 'mongodb://mongos0.example.com:27017,mongos1.example.com:27017/'
client = AsyncIOMotorClient(uriString)
wc_majority = WriteConcern("majority", wtimeout=1000)
# Prereq: Create collections.
await client.get_database("mydb1", write_concern=wc_majority).foo.insert_one({"abc": 0})
await client.get_database("mydb2", write_concern=wc_majority).bar.insert_one({"xyz": 0})
# Step 1: Define the callback that specifies the sequence of operations to perform inside the transactions.
async def callback(my_session):
collection_one = my_session.client.mydb1.foo
collection_two = my_session.client.mydb2.bar
# Important:: You must pass the session to the operations.
await collection_one.insert_one({"abc": 1}, session=my_session)
await collection_two.insert_one({"xyz": 999}, session=my_session)
# Step 2: Start a client session.
async with await client.start_session() as session:
# Step 3: Use with_transaction to start a transaction, execute the callback, and commit (or abort on error).
await session.with_transaction(
callback,
read_concern=ReadConcern("local"),
write_concern=wc_majority,
read_preference=ReadPreference.PRIMARY,
)

Este ejemplo resalta los componentes clave de la API de transacciones. En particular, utiliza la API de función de retorno. La API de función de retorno:

  • inicia una transacción

  • ejecuta las operaciones especificadas

  • confirma el resultado o finaliza la transacción en caso de error

Los errores en las operaciones del lado del servidor, como el DuplicateKeyError, pueden finalizar la transacción y producir un error de comando para alertar al usuario de que la transacción ha terminado. Este comportamiento es esperado y ocurre incluso si el cliente nunca llama a Session.abortTransaction(). Para incorporar una gestión personalizada de errores, se debe usar la Core API en la transacción.

La callback API incorpora lógica de reintento para ciertos errores. El controlador intenta volver a ejecutar la transacción después de un TransientTransactionError o un error de confirmación UnknownTransactionCommitResult.

A partir de MongoDB,6.0.5 el servidor no vuelve a intentar la transacción si recibe un error TransactionTooLargeForCache.

A partir de MongoDB 8.1, si una operación upsert se ejecuta en una transacción de múltiples documentos, entonces upsert no vuelve a intentarlo cuando encuentra un error de clave duplicada.

Importante

// For a replica set, include the replica set name and a seedlist of the members in the URI string; e.g.
// const uri = 'mongodb://mongodb0.example.com:27017,mongodb1.example.com:27017/?replicaSet=myRepl'
// For a sharded cluster, connect to the mongos instances; e.g.
// const uri = 'mongodb://mongos0.example.com:27017,mongos1.example.com:27017/'
const client = new MongoClient(uri);
await client.connect();
// Prereq: Create collections.
await client
.db('mydb1')
.collection('foo')
.insertOne({ abc: 0 }, { writeConcern: { w: 'majority' } });
await client
.db('mydb2')
.collection('bar')
.insertOne({ xyz: 0 }, { writeConcern: { w: 'majority' } });
// Step 1: Start a Client Session
const session = client.startSession();
// Step 2: Optional. Define options to use for the transaction
const transactionOptions = {
readPreference: 'primary',
readConcern: { level: 'local' },
writeConcern: { w: 'majority' }
};
// Step 3: Use withTransaction to start a transaction, execute the callback, and commit (or abort on error)
// Note: The callback for withTransaction MUST be async and/or return a Promise.
try {
await session.withTransaction(async () => {
const coll1 = client.db('mydb1').collection('foo');
const coll2 = client.db('mydb2').collection('bar');
// Important:: You must pass the session to the operations
await coll1.insertOne({ abc: 1 }, { session });
await coll2.insertOne({ xyz: 999 }, { session });
}, transactionOptions);
} finally {
await session.endSession();
await client.close();
}

Este ejemplo resalta los componentes clave de la API de transacciones. En particular, utiliza la API de función de retorno. La API de función de retorno:

  • inicia una transacción

  • ejecuta las operaciones especificadas

  • confirma el resultado o finaliza la transacción en caso de error

Los errores en las operaciones del lado del servidor, como el DuplicateKeyError, pueden finalizar la transacción y producir un error de comando para alertar al usuario de que la transacción ha terminado. Este comportamiento es esperado y ocurre incluso si el cliente nunca llama a Session.abortTransaction(). Para incorporar una gestión personalizada de errores, se debe usar la Core API en la transacción.

La callback API incorpora lógica de reintento para ciertos errores. El controlador intenta volver a ejecutar la transacción después de un TransientTransactionError o un error de confirmación UnknownTransactionCommitResult.

A partir de MongoDB,6.0.5 el servidor no vuelve a intentar la transacción si recibe un error TransactionTooLargeForCache.

A partir de MongoDB 8.1, si una operación upsert se ejecuta en una transacción de múltiples documentos, entonces upsert no vuelve a intentarlo cuando encuentra un error de clave duplicada.

Importante

sub runTransactionWithRetry {
my ( $txnFunc, $session ) = @_;
LOOP: {
eval {
$txnFunc->($session); # performs transaction
};
if ( my $error = $@ ) {
print("Transaction aborted-> Caught exception during transaction.\n");
# If transient error, retry the whole transaction
if ( $error->has_error_label("TransientTransactionError") ) {
print("TransientTransactionError, retrying transaction ->..\n");
redo LOOP;
}
else {
die $error;
}
}
}
return;
}
sub commitWithRetry {
my ($session) = @_;
LOOP: {
eval {
$session->commit_transaction(); # Uses write concern set at transaction start.
print("Transaction committed->\n");
};
if ( my $error = $@ ) {
# Can retry commit
if ( $error->has_error_label("UnknownTransactionCommitResult") ) {
print("UnknownTransactionCommitResult, retrying commit operation ->..\n");
redo LOOP;
}
else {
print("Error during commit ->..\n");
die $error;
}
}
}
return;
}
# Updates two collections in a transactions
sub updateEmployeeInfo {
my ($session) = @_;
my $employeesCollection = $session->client->ns("hr.employees");
my $eventsCollection = $session->client->ns("reporting.events");
$session->start_transaction(
{
readConcern => { level => "snapshot" },
writeConcern => { w => "majority" },
readPreference => 'primary',
}
);
eval {
$employeesCollection->update_one(
{ employee => 3 }, { '$set' => { status => "Inactive" } },
{ session => $session},
);
$eventsCollection->insert_one(
{ employee => 3, status => { new => "Inactive", old => "Active" } },
{ session => $session},
);
};
if ( my $error = $@ ) {
print("Caught exception during transaction, aborting->\n");
$session->abort_transaction();
die $error;
}
commitWithRetry($session);
}
# Start a session
my $session = $client->start_session();
eval {
runTransactionWithRetry(\&updateEmployeeInfo, $session);
};
if ( my $error = $@ ) {
# Do something with error
}
$session->end_session();

Este ejemplo resalta los componentes clave de la API de transacciones. En particular, utiliza la API de función de retorno. La API de función de retorno:

  • inicia una transacción

  • ejecuta las operaciones especificadas

  • confirma el resultado o finaliza la transacción en caso de error

Los errores en las operaciones del lado del servidor, como el DuplicateKeyError, pueden finalizar la transacción y producir un error de comando para alertar al usuario de que la transacción ha terminado. Este comportamiento es esperado y ocurre incluso si el cliente nunca llama a Session.abortTransaction(). Para incorporar una gestión personalizada de errores, se debe usar la Core API en la transacción.

La callback API incorpora lógica de reintento para ciertos errores. El controlador intenta volver a ejecutar la transacción después de un TransientTransactionError o un error de confirmación UnknownTransactionCommitResult.

A partir de MongoDB,6.0.5 el servidor no vuelve a intentar la transacción si recibe un error TransactionTooLargeForCache.

A partir de MongoDB 8.1, si una operación upsert se ejecuta en una transacción de múltiples documentos, entonces upsert no vuelve a intentarlo cuando encuentra un error de clave duplicada.

Importante

/*
* For a replica set, include the replica set name and a seedlist of the members in the URI string; e.g.
* uriString = 'mongodb://mongodb0.example.com:27017,mongodb1.example.com:27017/?replicaSet=myRepl'
* For a sharded cluster, connect to the mongos instances; e.g.
* uriString = 'mongodb://mongos0.example.com:27017,mongos1.example.com:27017/'
*/
$client = new \MongoDB\Client($uriString);
// Prerequisite: Create collections.
$client->selectCollection(
'mydb1',
'foo',
[
'writeConcern' => new \MongoDB\Driver\WriteConcern(\MongoDB\Driver\WriteConcern::MAJORITY, 1000),
],
)->insertOne(['abc' => 0]);
$client->selectCollection(
'mydb2',
'bar',
[
'writeConcern' => new \MongoDB\Driver\WriteConcern(\MongoDB\Driver\WriteConcern::MAJORITY, 1000),
],
)->insertOne(['xyz' => 0]);
// Step 1: Define the callback that specifies the sequence of operations to perform inside the transactions.
$callback = function (\MongoDB\Driver\Session $session) use ($client): void {
$client
->selectCollection('mydb1', 'foo')
->insertOne(['abc' => 1], ['session' => $session]);
$client
->selectCollection('mydb2', 'bar')
->insertOne(['xyz' => 999], ['session' => $session]);
};
// Step 2: Start a client session.
$session = $client->startSession();
// Step 3: Use with_transaction to start a transaction, execute the callback, and commit (or abort on error).
\MongoDB\with_transaction($session, $callback);

Este ejemplo resalta los componentes clave de la API de transacciones. En particular, utiliza la API de función de retorno. La API de función de retorno:

  • inicia una transacción

  • ejecuta las operaciones especificadas

  • confirma el resultado o finaliza la transacción en caso de error

Los errores en las operaciones del lado del servidor, como el DuplicateKeyError, pueden finalizar la transacción y producir un error de comando para alertar al usuario de que la transacción ha terminado. Este comportamiento es esperado y ocurre incluso si el cliente nunca llama a Session.abortTransaction(). Para incorporar una gestión personalizada de errores, se debe usar la Core API en la transacción.

La callback API incorpora lógica de reintento para ciertos errores. El controlador intenta volver a ejecutar la transacción después de un TransientTransactionError o un error de confirmación UnknownTransactionCommitResult.

A partir de MongoDB,6.0.5 el servidor no vuelve a intentar la transacción si recibe un error TransactionTooLargeForCache.

A partir de MongoDB 8.1, si una operación upsert se ejecuta en una transacción de múltiples documentos, entonces upsert no vuelve a intentarlo cuando encuentra un error de clave duplicada.

Importante

# For a replica set, include the replica set name and a seedlist of the members in the URI string; e.g.
# uriString = 'mongodb://mongodb0.example.com:27017,mongodb1.example.com:27017/?replicaSet=myRepl'
# For a sharded cluster, connect to the mongos instances; e.g.
# uriString = 'mongodb://mongos0.example.com:27017,mongos1.example.com:27017/'
client = MongoClient(uriString)
wc_majority = WriteConcern("majority", wtimeout=1000)
# Prereq: Create collections.
client.get_database("mydb1", write_concern=wc_majority).foo.insert_one({"abc": 0})
client.get_database("mydb2", write_concern=wc_majority).bar.insert_one({"xyz": 0})
# Step 1: Define the callback that specifies the sequence of operations to perform inside the transactions.
def callback(session):
collection_one = session.client.mydb1.foo
collection_two = session.client.mydb2.bar
# Important:: You must pass the session to the operations.
collection_one.insert_one({"abc": 1}, session=session)
collection_two.insert_one({"xyz": 999}, session=session)
# Step 2: Start a client session.
with client.start_session() as session:
# Step 3: Use with_transaction to start a transaction, execute the callback, and commit (or abort on error).
session.with_transaction(callback)

Este ejemplo resalta los componentes clave de la API de transacciones. En particular, utiliza la API de función de retorno. La API de función de retorno:

  • inicia una transacción

  • ejecuta las operaciones especificadas

  • confirma el resultado o finaliza la transacción en caso de error

Los errores en las operaciones del lado del servidor, como el DuplicateKeyError, pueden finalizar la transacción y producir un error de comando para alertar al usuario de que la transacción ha terminado. Este comportamiento es esperado y ocurre incluso si el cliente nunca llama a Session.abortTransaction(). Para incorporar una gestión personalizada de errores, se debe usar la Core API en la transacción.

La callback API incorpora lógica de reintento para ciertos errores. El controlador intenta volver a ejecutar la transacción después de un TransientTransactionError o un error de confirmación UnknownTransactionCommitResult.

A partir de MongoDB,6.0.5 el servidor no vuelve a intentar la transacción si recibe un error TransactionTooLargeForCache.

A partir de MongoDB 8.1, si una operación upsert se ejecuta en una transacción de múltiples documentos, entonces upsert no vuelve a intentarlo cuando encuentra un error de clave duplicada.

Importante

# For a replica set, include the replica set name and a seedlist of the members in the URI string; e.g.
# uriString = 'mongodb://mongodb0.example.com:27017,mongodb1.example.com:27017/?replicaSet=myRepl'
# For a sharded cluster, connect to the mongos instances; e.g.
# uri_string = 'mongodb://mongos0.example.com:27017,mongos1.example.com:27017/'
client = Mongo::Client.new(uri_string, write_concern: {w: :majority, wtimeout: 1000})
# Prereq: Create collections.
client.use('mydb1')['foo'].insert_one(abc: 0)
client.use('mydb2')['bar'].insert_one(xyz: 0)
# Step 1: Define the callback that specifies the sequence of operations to perform inside the transactions.
callback = Proc.new do |my_session|
collection_one = client.use('mydb1')['foo']
collection_two = client.use('mydb2')['bar']
# Important: You must pass the session to the operations.
collection_one.insert_one({'abc': 1}, session: my_session)
collection_two.insert_one({'xyz': 999}, session: my_session)
end
#. Step 2: Start a client session.
session = client.start_session
# Step 3: Use with_transaction to start a transaction, execute the callback, and commit (or abort on error).
session.with_transaction(
read_concern: {level: :local},
write_concern: {w: :majority, wtimeout: 1000},
read: {mode: :primary},
&callback)

Este ejemplo resalta los componentes clave de la API de transacciones. En particular, utiliza la API de función de retorno. La API de función de retorno:

  • inicia una transacción

  • ejecuta las operaciones especificadas

  • confirma el resultado o finaliza la transacción en caso de error

Los errores en las operaciones del lado del servidor, como el DuplicateKeyError, pueden finalizar la transacción y producir un error de comando para alertar al usuario de que la transacción ha terminado. Este comportamiento es esperado y ocurre incluso si el cliente nunca llama a Session.abortTransaction(). Para incorporar una gestión personalizada de errores, se debe usar la Core API en la transacción.

La callback API incorpora lógica de reintento para ciertos errores. El controlador intenta volver a ejecutar la transacción después de un TransientTransactionError o un error de confirmación UnknownTransactionCommitResult.

A partir de MongoDB,6.0.5 el servidor no vuelve a intentar la transacción si recibe un error TransactionTooLargeForCache.

A partir de MongoDB 8.1, si una operación upsert se ejecuta en una transacción de múltiples documentos, entonces upsert no vuelve a intentarlo cuando encuentra un error de clave duplicada.

Importante

// Prereq: Create collections. CRUD operations in transactions must be on existing collections.
client
.database("mydb1")
.collection::<Document>("foo")
.insert_one(doc! { "abc": 0})
.await?;
client
.database("mydb2")
.collection::<Document>("bar")
.insert_one(doc! { "xyz": 0})
.await?;
// Step 1: Define the callback that specifies the sequence of operations to perform inside the
// transaction.
async fn callback(session: &mut ClientSession) -> Result<()> {
let collection_one = session
.client()
.database("mydb1")
.collection::<Document>("foo");
let collection_two = session
.client()
.database("mydb2")
.collection::<Document>("bar");
// Important: You must pass the session to the operations.
collection_one
.insert_one(doc! { "abc": 1 })
.session(&mut *session)
.await?;
collection_two
.insert_one(doc! { "xyz": 999 })
.session(session)
.await?;
Ok(())
}
// Step 2: Start a client session.
let mut session = client.start_session().await?;
// Step 3: Use and_run2 to start a transaction, execute the callback, and commit (or
// abort on error).
session.start_transaction().and_run2(callback).await?;

Este ejemplo utiliza la Core API. Dado que la Core API no incorpora lógica de reintentos para los errores de TransientTransactionError o UnknownTransactionCommitResult de confirmación, el ejemplo incluye lógica explícita para reintentar la transacción para estos errores:

Importante

/*
* Copyright 2008-present MongoDB, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.mongodb.scala
import org.mongodb.scala.model.{Filters, Updates}
import org.mongodb.scala.result.UpdateResult
import scala.concurrent.Await
import scala.concurrent.duration.Duration
//scalastyle:off magic.number
class DocumentationTransactionsExampleSpec extends RequiresMongoDBISpec {
// Implicit functions that execute the Observable and return the results
val waitDuration = Duration(5, "seconds")
implicit class ObservableExecutor[T](observable: Observable[T]) {
def execute(): Seq[T] = Await.result(observable.toFuture(), waitDuration)
}
implicit class SingleObservableExecutor[T](observable: SingleObservable[T]) {
def execute(): T = Await.result(observable.toFuture(), waitDuration)
}
// end implicit functions
"The Scala driver" should "be able to commit a transaction" in withClient { client =>
assume(serverVersionAtLeast(List(4, 0, 0)) && !hasSingleHost())
client.getDatabase("hr").drop().execute()
client.getDatabase("hr").createCollection("employees").execute()
client.getDatabase("hr").createCollection("events").execute()
updateEmployeeInfoWithRetry(client).execute() should equal(Completed())
client.getDatabase("hr").drop().execute() should equal(Completed())
}
def updateEmployeeInfo(database: MongoDatabase, observable: SingleObservable[ClientSession]): SingleObservable[ClientSession] = {
observable.map(clientSession => {
val employeesCollection = database.getCollection("employees")
val eventsCollection = database.getCollection("events")
val transactionOptions = TransactionOptions.builder()
.readPreference(ReadPreference.primary())
.readConcern(ReadConcern.SNAPSHOT)
.writeConcern(WriteConcern.MAJORITY)
.build()
clientSession.startTransaction(transactionOptions)
employeesCollection.updateOne(clientSession, Filters.eq("employee", 3), Updates.set("status", "Inactive"))
.subscribe((res: UpdateResult) => println(res))
eventsCollection.insertOne(clientSession, Document("employee" -> 3, "status" -> Document("new" -> "Inactive", "old" -> "Active")))
.subscribe((res: Completed) => println(res))
clientSession
})
}
def commitAndRetry(observable: SingleObservable[Completed]): SingleObservable[Completed] = {
observable.recoverWith({
case e: MongoException if e.hasErrorLabel(MongoException.UNKNOWN_TRANSACTION_COMMIT_RESULT_LABEL) => {
println("UnknownTransactionCommitResult, retrying commit operation ...")
commitAndRetry(observable)
}
case e: Exception => {
println(s"Exception during commit ...: $e")
throw e
}
})
}
def runTransactionAndRetry(observable: SingleObservable[Completed]): SingleObservable[Completed] = {
observable.recoverWith({
case e: MongoException if e.hasErrorLabel(MongoException.TRANSIENT_TRANSACTION_ERROR_LABEL) => {
println("TransientTransactionError, aborting transaction and retrying ...")
runTransactionAndRetry(observable)
}
})
}
def updateEmployeeInfoWithRetry(client: MongoClient): SingleObservable[Completed] = {
val database = client.getDatabase("hr")
val updateEmployeeInfoObservable: Observable[ClientSession] = updateEmployeeInfo(database, client.startSession())
val commitTransactionObservable: SingleObservable[Completed] =
updateEmployeeInfoObservable.flatMap(clientSession => clientSession.commitTransaction())
val commitAndRetryObservable: SingleObservable[Completed] = commitAndRetry(commitTransactionObservable)
runTransactionAndRetry(commitAndRetryObservable)
}
}

Tip

Para un ejemplo en mongosh, consulta mongosh Ejemplo.

Para situaciones que requieren atomicidad de las lecturas y escrituras en varios documentos (en una sola colección o en varias), MongoDB admite transacciones distribuidas, incluidas las transacciones en sets de réplica y clústeres fragmentados.

Las transacciones distribuidas son atómicas:

  • Las transacciones aplican todos los cambios de datos o los revierten.

  • Si una transacción se confirma, todos los cambios de datos realizados en la transacción se guardan y son visibles fuera de la transacción.

    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 en la transacción se descartan sin llegar a ser visibles. Por ejemplo, si alguna operación en la transacción falla, la transacción se aborta y todos los cambios de datos realizados en la transacción se descartan sin llegar a ser visibles.

Importante

En la mayoría de los casos, una transacción distribuida incurre en un costo de rendimiento mayor que las escrituras de documentos individuales, y la disponibilidad de transacciones distribuidas no debería ser un sustituto para un diseño de esquema efectivo. Para muchos casos, el modelo de datos desnormalizado (documento incrustado y matrices) seguirá siendo óptimo para tus datos y casos de uso. Es decir, en muchos casos, modelar tus datos de forma adecuada minimizará la necesidad de transacciones distribuidas.

Para consideraciones adicionales sobre el uso de transacciones (como el límite de tiempo de ejecución y el límite de tamaño del oplog), consulta también las consideraciones de producción.

Las transacciones distribuidas pueden utilizarse en múltiples operaciones, colecciones, bases de datos, documentos y particiones.

Para las transacciones:

  • Puedes crear colecciones e índices en transacciones. Para obtener más detalles, consulta 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, admin o local.

  • No se puede escribir en las colecciones de system.*.

  • No puedes devolver el plan de query de las operaciones admitidas usando explain o comandos similares.

  • Para los cursores creados fuera de una transacción, no puedes llamar a getMore dentro de la transacción.

  • Para los cursores creados en una transacción, no puedes llamar a getMore fuera de la transacción.

  • No puedes especificar el comando killCursors como la primera operación en una transacción.

    Además, si ejecutas el comando killCursors dentro de una transacción, el servidor detiene inmediatamente los cursores especificados. No espera la confirmación de la transacción.

Para obtener una lista de las operaciones no admitidas en las transacciones, consulta Operaciones restringidas.

Tip

Al crear o descartar una colección inmediatamente antes de iniciar una transacción, si se accede a la colección dentro de la transacción, realice la operación de creación o descarte con el nivel de confirmación de escritura "majority" para asegurarse de que la transacción pueda adquirir los bloqueos necesarios.

Puedes realizar las siguientes operaciones en una transacción distribuida si la transacción no es una transacción de escritura entre fragmentos:

  • Crea colecciones.

  • Crea índices en nuevas colecciones vacías que se hayan creado anteriormente en la misma transacción.

Al crear una colección dentro de una transacción:

Cuando cree un índice dentro de una transacción [1], el índice que se va a crear debe estar en uno de los siguientes:

  • una colección inexistente. La colección se crea como parte de la operación.

  • una nueva colección vacía creada anteriormente en la misma transacción.

[1] También puede ejecutar db.collection.createIndex() y db.collection.createIndexes() en índices existentes para comprobar su existencia. Estas operaciones se completan con éxito sin crear el índice.
  • 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 usar la etapa $graphLookup dentro de una transacción durante el direccionamiento a una colección fragmentada.

  • Para la creación explícita de una colección o un índice dentro de una transacción, el nivel de consistencia de lectura de la transacción debe ser "local".

    Para crear explícitamente colecciones e índices, utiliza los siguientes comandos y métodos:

    Comando
    Método

Para realizar una operación de conteo dentro de una transacción, utilice la etapa de agregación $count o la etapa de agregación $group (con una expresión $sum).

Los controladores de MongoDB proporcionan una API a nivel de colección countDocuments(filter, options) como un método asistente que utiliza el $group con una expresión $sum para realizar un conteo.

mongosh proporciona el método asistente db.collection.countDocuments() que utiliza $group con una expresión $sum para realizar un conteo.

Para realizar una operación específica dentro de una transacción:

  • Para colecciones no fragmentadas, puedes utilizar el método db.collection.distinct() o el comando distinct, así como la canalización de agregación con la etapa $group.

  • Para colecciones fragmentadas, no puede utilizar el método db.collection.distinct() ni el comando distinct.

    Para encontrar los valores distintos de una colección fragmentada, utilice la canalización de agregación con la etapa $group en su lugar. Por ejemplo:

    • En lugar de db.coll.distinct("x"), utilice

      db.coll.aggregate([
      { $group: { _id: null, distinctValues: { $addToSet: "$x" } } },
      { $project: { _id: 0 } }
      ])
    • En lugar de db.coll.distinct("x", { status: "A" }), utilice:

      db.coll.aggregate([
      { $match: { status: "A" } },
      { $group: { _id: null, distinctValues: { $addToSet: "$x" } } },
      { $project: { _id: 0 } }
      ])

    El pipeline devuelve un cursor a un documento:

    { "distinctValues" : [ 2, 3, 1 ] }

    Itere el cursor para acceder al documento de resultados.

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.

Las siguientes operaciones no están permitidas en las transacciones:

  • Las transacciones están asociadas a una sesión.

  • Puede tener como máximo una transacción abierta a la vez para una sesión.

  • Cuando se utilizan los drivers, cada operación en la transacción debe estar asociada a la sesión. Se debe consultar la documentación específica del driver para conseguir más detalles.

  • Si una sesión termina y tiene una transacción abierta, la transacción se abortará.

Las operaciones en una transacción utilizan la preferencia de lectura a nivel de transacción.

Usando los drivers, se puede establecer la preferencia de lectura a nivel de transacción al inicio de la transacción:

  • Si la preferencia de lectura a nivel de transacción no está establecida, la transacción utiliza la preferencia de lectura a nivel de sesión.

  • Si la preferencia de lectura a nivel de transacción y la de nivel de sesión no están establecidas, la transacción utiliza la preferencia de lectura a nivel de cliente. Por defecto, la preferencia de lectura a nivel de cliente es primary.

Las transacciones distribuidas que contienen operaciones de lectura deben usar la preferencia de lectura primary. Todas las operaciones en una transacción dada deben dirigirse al mismo nodo.

Las operaciones en una transacción utilizan el nivel de consistencia de lectura de la transacción. Esto significa que un nivel de consistencia de lectura establecido a nivel de colección y base de datos se ignora dentro de la transacción.

Puede establecer el nivel de consistencia de lectura a nivel de transacción al inicio de la transacción.

  • Si el nivel de consistencia de lectura a nivel de transacción no está establecido, el nivel de consistencia de lectura a nivel de transacción por defecto se ajusta al nivel de consistencia de lectura a nivel de sesión.

  • Si el nivel de consistencia de lectura de transacción y el de sesión no están configurados, el nivel de consistencia de lectura de transacción por defecto es el nivel de consistencia de lectura de cliente. Por defecto, el nivel de consistencia de lectura de es "local" para las lecturas en el primario. Véase también:

Las transacciones soportan los siguientes niveles de consistencia de lectura:

  • El nivel de consistencia de lectura "local" devuelve los datos más recientes disponibles del nodo, pero puede ser revertido.

  • En un set de réplicas, incluso si una transacción utiliza un nivel de consistencia de lectura de local, es posible que observe un aislamiento de lectura más fuerte, donde la operación lee desde un snapshot en el punto en el que se abrió la transacción.

  • Para las transacciones en un clúster, el nivel de consistencia de lectura "local" no puede garantizar que los datos provengan de la misma vista de snapshot en todos los fragmentos. Si se requiere el aislamiento de snapshot, utiliza un "snapshot" nivel de consistencia de lectura.

  • Puedes crear colecciones e índices dentro de una transacción. Si creas explícitamente una colección o un índice, la transacción debe usar el nivel de consistencia de lectura "local". Si creas implícitamente una colección, puedes utilizar cualquiera de los niveles de consistencia de lectura disponibles para las transacciones.

  • Si la transacción se confirma con el nivel de confirmación de escritura "mayoría", el nivel de consistencia de lectura "majority" devuelve datos que hayan sido reconocidos por la mayoría de los miembros del set de réplicas y no se pueden revertir. De lo contrario, el nivel de consistencia de lectura "majority" no ofrece garantías de que las operaciones de lectura accedan a datos comprometidos por la mayoría.

  • Para las transacciones en un clúster fragmentado, el nivel de consistencia de lectura "majority" no puede garantizar que los datos provengan de la misma vista de snapshot en todos los fragmentos. Si se requiere el aislamiento de snapshot, utiliza el nivel de consistencia de lectura "snapshot".

Las transacciones utilizan el nivel de confirmación de escritura a nivel de transacción para confirmar las operaciones de escritura. Las operaciones de escritura dentro de las transacciones deben ejecutarse sin una especificación explícita de nivel de confirmación de escritura y utilizar el nivel de confirmación de escritura por defecto. En el momento de la confirmación, las escrituras se confirmaron utilizando el nivel de confirmación de escritura a nivel de transacción.

Tip

No establezca explícitamente el nivel de confirmación de escritura para las operaciones de escritura individuales dentro de una transacción. Configurar niveles de confirmación de escritura para las operaciones de escritura individuales dentro de una transacción genera un error.

Puede establecer el nivel de confirmación de escritura a nivel de transacción al inicio de la transacción:

  • Si el nivel de confirmación de escritura a nivel de transacción no está establecido, se utiliza por defecto el nivel de confirmación de escritura a nivel de sesión para la confirmación.

  • Si el nivel de confirmación de escritura a nivel de transacción y el nivel de confirmación de escritura a nivel de sesión no están configurados, el nivel de confirmación de escritura a nivel de transacción por defecto es el nivel de confirmación de escritura a nivel de cliente de:

Las transacciones tienen soporte para todos los valores de w de nivel de confirmación de escritura, incluidos:

  • El nivel de confirmación de escritura w: 1 devuelve un reconocimiento después de que la confirmación se haya aplicado al primario.

    Importante

    Cuando se realiza una confirmación w: 1, la transacción puede revertirse si hay una conmutación por error.

  • Cuando confirma el nivel de confirmación de escritura w: 1, el nivel de consistencia de lectura a nivel de transacción "majority" no ofrece garantías de que las operaciones de lectura en la transacción lean datos confirmados por la mayoría.

  • Cuando se confirma el nivel de confirmación de escritura w: 1, el nivel de consistencia de lectura a nivel de transacción "snapshot" no proporciona garantías de que las operaciones de lectura en la transacción hayan utilizado una snapshot de los datos confirmados por la mayoría.

  • El nivel de confirmación de escritura w: "majority" devuelve un reconocimiento después de que la confirmación se haya aplicado a la mayoría de los miembros con derecho a voto.

  • Cuando se confirma el nivel de confirmación de escritura w: "majority", el nivel de consistencia de lectura a nivel de transacción "majority" garantiza que las operaciones hayan leído datos confirmados por la mayoría. Para las transacciones en clústeres particionados, esta vista de los datos confirmados por la mayoría no se sincroniza entre los fragmentos.

  • Cuando se confirma el nivel de confirmación de escritura w: "majority", el nivel de consistencia de lectura a nivel de transacción "snapshot" ofrece garantías de que las operaciones han leído de una snapshot sincronizada de datos confirmados por la mayoría.

Nota

Independientemente del nivel de confirmación de escritura especificado para la transacción, la operación de confirmación para una transacción de clúster incluye algunas partes que utilizan el nivel de confirmación de escritura {w: "majority", j: true}.

El parámetro del servidor coordinateCommitReturnImmediatelyAfterPersistingDecision controla cuándo se devuelven las decisiones de confirmación de transacción al cliente.

El parámetro se introdujo en MongDB 5.0 con un valor predeterminado de true. En MongoDB 6.0 y 5.0.10, el valor predeterminado cambia a false.

Cuando coordinateCommitReturnImmediatelyAfterPersistingDecision es false, el coordinador de transacciones de partición espera a que todos los miembros confirmen una transacción multi-documento antes de devolver la decisión de confirmación al cliente.

Si especificas un nivel de confirmación de escritura "majority" para operaciones de guardar documentos individuales y múltiples y la operación no se replica a la mayoría calculada de los miembros del set de réplicas antes de que devuelva una respuesta, entonces los datos eventualmente se replican o se revierten. Consulta wtimeout.

Independientemente del nivel de confirmación de escritura especificado para la transacción, el controlador aplica w: "majority" como nivel de confirmación de escritura al volver a intentar commitTransaction.

Las siguientes secciones describen más consideraciones para las transacciones.

Para transacciones en entornos de producción, consulte Consideraciones de producción. Además, para clústeres fragmentados, consulte Consideraciones de producción (Clústeres fragmentados).

No puedes cambiar una clave de fragmentación mediante una transacción si el set de réplicas tiene un árbitro. Los árbitros no pueden participar en las operaciones de datos requeridas para las transacciones de múltiples fragmentos.

Las transacciones cuyas operaciones de escritura abarcan varios fragmentos generarán un error y se abortarán si alguna operación de transacción lee o escribe en una partición que contiene un árbitro.

No puedes ejecutar transacciones en un clúster que tenga una partición con writeConcernMajorityJournalDefault configurado en false (como una partición con un nodo votante que utiliza el motor de almacenamiento en memoria).

Nota

Independientemente del nivel de confirmación de escritura especificado para la transacción, la operación de confirmación para una transacción de clúster incluye algunas partes que utilizan el nivel de confirmación de escritura {w: "majority", j: true}.

Para obtener el estado de la transacción y las métricas, utilice los siguientes métodos:

Origen
Devuelve

Devuelve las métricas de transacciones.

Algunos serverStatus campos de respuesta no se devuelven en0 clústeres M ni Flex de MongoDB Atlas. Para obtener más información, consulte Comandos limitados en la documentación de MongoDB Atlas.

$currentOp Aggregation Pipeline

Devuelve:

Devuelve:

mongod y mensajes de registro de mongos

Incluye información sobre las transacciones lentas (que son transacciones que superan el umbral de operationProfiling.slowOpThresholdMs) en el componente de registro TXN.

Para utilizar transacciones, la featureCompatibilityVersion de todos los miembros de la implementación debe ser al menos:

Implementación
Mínimo featureCompatibilityVersion

Set de réplicas

4.0

Clúster fragmentado

4.2

Para comprobar la compatibilidad de características entre versiones de un nodo, conéctese al nodo y ejecute el siguiente comando:

db.adminCommand( { getParameter: 1, featureCompatibilityVersion: 1 } )

Para obtener más información, consulte la página de referencia setFeatureCompatibilityVersion.

Las transacciones distribuidas son compatibles con los sets de réplicas y los clústeres fragmentados donde:

  • el primario utiliza el motor de almacenamiento WiredTiger, y

  • los miembros secundarios utilizan el motor de almacenamiento WiredTiger o los motores de almacenamiento en memoria.

Nota

No se pueden ejecutar transacciones en un clúster fragmentado que tenga un fragmento con writeConcernMajorityJournalDefault establecido false en, como un fragmento con un miembro con derecho a voto que use el motor de almacenamiento en memoria.

A partir de MongoDB 5.2 (y 5.0.4):

Volver

update

En esta página