Menu Docs
Página inicial do Docs
/
Manual do MongoDB
/ / / /

Session.startTransaction()

Nesta página

  • Definição
  • Comportamento
  • Exemplo
Session.startTransaction(<options>)

Inicia umatransação multidocumento associada à sessão. A qualquer momento, você pode ter no máximo uma transação aberta em uma sessão.

Observação

Esta operação é um no-op. A transação não iniciará no servidor até que o primeiro comando seja enviado na sessão. Portanto, o tempo de snapshot da transação não será definido até que o primeiro comando seja enviado na sessão.

Transações multidocumento estão disponíveis tanto para clusters fragmentados quanto para conjuntos de réplicas.

Importante

Em uma transação, você só pode especificar operações de leitura e gravação (CRUD) em collections existentes . Por exemplo, uma transação multidocumento não pode incluir uma operação de inserção que resultaria na criação de uma nova collection.

O método Session.startTransaction() pode levar um documento com as seguintes opções:

{ readConcern: { level: <level>}, writeConcern: { w: <value>, j: <boolean>, wtimeout: <number> } }
Opção
Descrição
readConcern

Opcional. Um documento que especifica o read concern para todas as operações na transação, substituindo o read concern específico da operação.

Você pode especificar um dos seguintes níveis de read concern:

  • "snapshot"

  • "local"

  • "majority"

Para os read concerns "local" e "majority", o MongoDB pode, às vezes, substituir um read concern mais forte.

writeConcern

Opcional. Um documento que especifica o write concern da transação. Essa write concern se aplica às operações de confirmação e anulação da transação.

As operações dentro da transação usam "w: 1", substituindo o write concern específico da operação.

Se você se comprometer usando "w: 1" write concern, sua transação poderá ser revertida durante o processo de failover.

Para drivers do MongoDB, as transações usam o write concern no nível do cliente como padrão.

Observação

Se estiver executando com controle de acesso, você deverá ter privilégios para as operações na transação.

Para transações com vários documentos:

  • Você pode criar coleções e índices em transações. Para obter detalhes, consulte Crie coleções e índices em uma transação

  • A coletas utilizadas em uma transação podem estar em diferentes bancos de dados.

    Observação

    Você não pode criar uma nova coleta em transações de gravação entre fragmentos. Por exemplo, se você gravar em uma coleta existente em um fragmento e criar implicitamente uma coleta em um fragmento diferente, o MongoDB não poderá executar ambas as operações na mesma transação.

  • Você não pode gravar em coletas limitadas .

  • Não é possível usar read concern "snapshot" ao ler em uma capped collection. (A partir do MongoDB 5.0)

  • Você não pode ler/gravar em coletas nos bancos de dados config, admin ou local.

  • Você não pode gravar na coleção system.*.

  • Não é possível retornar o plano de query da operação compatível utilizando explain ou comandos semelhantes.

  • Para cursores criados fora de uma transação, você não pode chamar getMore dentro da transação.

  • Para cursores criados em uma transação, não é possível chamar getMore fora da transação.

Método
Comando
Observação

Excluindo as seguintes expressões do operador de query:

O método utiliza o estágio de aggregation $match para a query e estágio de aggregation $group com uma expressão $sum para executar a contagem.

Disponível em coleções não partilhadas.

For sharded collections, use the aggregation pipeline with the $group stage. See Distinct Operation.

Se a operação de atualização ou substituição for executada com upsert: true em uma coleção inexistente, a coleção será implicitamente criada.

Para obter mais detalhes, consulte Operações de administração.

Se for executado em uma coleção inexistente, a coleção será criada implicitamente.

Para obter mais detalhes, consulte Operações de administração.

Se for executado em uma coleção inexistente, a coleção será criada implicitamente.

Para obter mais detalhes, consulte Operações de administração.

Se for executado em uma coleção inexistente, a coleção será criada implicitamente.

Para obter mais detalhes, consulte Operações de administração.

As operações que afetam o catálogo do banco de dados, como a criação ou eliminação de uma coleção ou de um índice, não são permitidas em transações multidocumento. Por exemplo, uma transação multidocumento não pode incluir uma operação de inserção que resultaria na criação de uma nova coleção. Consulte Operações restritas.

Comandos informativos, como hello, buildInfo, connectionStatus (e seus métodos de ajuda) são permitidos em transações; no entanto, eles não podem ser a primeira operação na transação.

As transações suportam read preference primary.

Enquanto a transação estiver aberta, nenhuma alteração de dados feita pelas operações na transação será visível fora da transação:

  • Quando uma transação é confirmada, todas as alterações de dados feitas na transação são salvas e visíveis fora da transação. Ou seja, uma transação não confirmará algumas de suas alterações enquanto reverte outras.

    Até que uma transação seja confirmada, as alterações de dados feitas na transação não serão visíveis fora da transação.

    No entanto, quando uma transação é gravada em vários fragmentos, nem todas as operações de leitura externas precisam esperar que o resultado da transação confirmada fique visível nos fragmentos. Por exemplo, se uma transação estiver comprometida e escrever 1 estiver visível no fragmento A, mas escrever 2 ainda não estiver visível no fragmento B, uma leitura externa em questão de leitura "local" poderá ler os resultados da escrita 1 sem ver a escrita 2.

  • 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.

Considere um cenário em que, à medida que as alterações são feitas no registro de um funcionário no banco de dados hr, você deseja garantir que a collection de events no banco de dados reporting esteja sincronizada com as alterações hr. Ou seja, você deseja garantir que essas gravações sejam feitas como uma única transação, de modo que ambas as operações sejam bem-sucedidas ou não.

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 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, atualiza o status de um funcionário para Inactive no status employees, insere um documento correspondente à collection events e comete as duas operações como uma única 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;
}
}
}
}
// 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();
}

Dica

Veja também:

Voltar

Session.commitTransaction()