Session.abortTransaction()
Nesta página
Definição
Session.abortTransaction()
Encerra atransação multidocumento e reverte todas as alterações de dados feitas pelas operações dentro da transação. Ou seja, a transação termina sem salvar nenhuma das alterações feitas pelas operações na transação.
Importante
Método mongosh
Esta página documenta um método
mongosh
. Esta não é a documentação de comandos de banco de dados nem drivers específicos de linguagem, como Node.js.Para o comando do banco de dados, consulte o comando
abortTransaction
.Para drivers de API do MongoDB, consulte a documentação do driver do MongoDB específica da linguagem.
Alterado na versão 4.2: A partir do MongoDB 4.2, as transação de vários documento estão disponíveis tanto para clusters fragmentados quanto para conjuntos de réplicas.
Comportamento
Atomicidade
Quando uma transação é cancelada, todas as alterações de dados feitas pelas gravações na transação são descartadas sem nunca se tornarem visíveis, e a transação termina.
Segurança
Se estiverem sendo executadas com auditoria, as operações em uma transação abortada ainda serão auditadas.
Repetitivo
Se a operação de cancelamento encontrar um erro, os drivers do MongoDB tentarão repeti-la uma única vez, independentemente de retryWrites
estar configurado como true
. Para obter mais informações, consulte Tratamento de erros de transação.
Exemplo
Considere um cenário no qual, à medida que são feitas alterações no registro de um funcionário no banco de dados hr
, você quer que a collection events
no banco de dados reporting
esteja sincronizada com as alterações de hr
e vice-versa. Ou seja, você deseja garantir que essas escritas sejam feitas como uma única transação, de forma que ambas as operações sejam bem-sucedidas ou falhem.
A collection employees
no banco de dados hr
tem os seguintes 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" }
A collection employees
tem um índice único no campo employee
:
db.employees.createIndex( { employee: 1 }, { unique: true } )
A collection events
no banco de dados reporting
tem os seguintes 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 } }
O exemplo a seguir abre uma transação e tenta adicionar um registro à collection events
e adicionar um documento à collection employees
. Se a operação encontrar um erro nas operações ou na confirmação da transação, a sessão cancelará a transação.
// 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; } } } } // Performs inserts and count in a transaction function updateEmployeeInfo(session) { employeesCollection = session.getDatabase("hr").employees; eventsCollection = session.getDatabase("reporting").events; // Start a transaction for the session that uses: // - read concern "snapshot" // - write concern "majority" session.startTransaction( { readConcern: { level: "snapshot" }, writeConcern: { w: "majority" } } ); try{ eventsCollection.insertOne( { employee: 3, status: { new: "Active", old: null }, department: { new: "XYZ", old: null } } ); // Count number of events for employee 3 var countDoc = eventsCollection.aggregate( [ { $match: { employee: 3 } }, { $count: "eventCounts" } ] ).next(); print( "events count (in active transaction): " + countDoc.eventCounts ); // The following operations should fail as an employee ``3`` already exist in employees collection employeesCollection.insertOne( { employee: 3, name: { title: "Miss", name: "Terri Bachs" }, status: "Active", department: "XYZ" } ); } catch (error) { print("Caught exception during transaction, aborting."); session.abortTransaction(); throw error; } commitWithRetry(session); } // End of updateEmployeeInfo function // Start a session. session = db.getMongo().startSession( { readPreference: { mode: "primary" } } ); try{ runTransactionWithRetry(updateEmployeeInfo, session); } catch (error) { // Do something with error } finally { session.endSession(); }