Join us Sept 17 at .local NYC! Use code WEB50 to save 50% on tickets. Learn more >
MongoDB Event
Menu Docs
Página inicial do Docs
/ / /
Controlador Node.js
/

Transações

Neste guia, você pode aprender a usar o driver Node.js para executar transações. As transações permitem que você execute uma série de operações que não alteram nenhum dado até que toda a transação seja confirmada. Se qualquer operação na transação falhar, o driver encerra a transação e descarta todas as alterações de dados antes que elas se tornem visíveis. Esse recurso é chamado de atomicidade.

Como todas as operações de gravação em um único documento no MongoDB são atômicas, convém usar transações para fazer uma alteração atômica que modifique vários documentos. Essa situação exige uma transação multidocumento. As transações de vários documentos são compatíveis com ACID porque o MongoDB garante que os dados envolvidos em suas operações de transação permaneçam consistentes, mesmo se o driver encontrar erros inesperados.

Para saber mais sobre conformidade com ACID e ACID transactions, consulte nosso artigo sobre transações ACID.

Observação

Para executar uma transação de vários documentos, você deve estar conectado a uma implementação executando o Servidor MongoDB versão 4.0 ou posterior.

Para obter uma lista detalhada das limitações, consulte a seção Transações e operações no manual do servidor.

Saiba mais sobre como usar o driver para realizar transações com vários documentos nas seguintes seções deste guia:

O MongoDB permite consistência causal em determinadas sessões de cliente. O modelo de consistência causal garante que, em um sistema distribuído, as operações dentro de uma sessão sejam executadas em uma ordem causal. Os clientes observam resultados consistentes com as relações causais ou as dependências entre as operações. Por exemplo, se você executar uma série de operações em que uma operação depende logicamente do resultado de outra, todas as leituras subsequentes refletirão o relacionamento de dependência .

Para garantir a consistência causal, as sessões de cliente devem atender aos seguintes requisitos:

  • Ao iniciar uma sessão, o driver deve habilitar a opção de consistência causal. Esta opção está habilitada por padrão.

  • As operações devem ser executadas em uma única sessão em um único thread. Caso contrário, as sessões ou threads devem comunicar os valores de optime e tempo de cluster uns aos outros. Para exibir um exemplo de duas sessões que comunicam esses valores, consulte os exemplos de Consistência causal no manual do MongoDB Server.

  • Você deve usar uma majority preocupação de leitura.

  • Você deve usar uma preocupação de gravação majority . Este é o valor padrão de preocupação de gravação .

A tabela a seguir descreve as garantias que as sessões causalmente consistentes oferecem:

Garantia
Descrição

Ler suas gravações

As operações de leitura refletem os resultados das operações de gravação anteriores.

Leituras monotônicas

As operações de leitura não retornam resultados que reflitam um estado de dados anterior a uma operação de leitura anterior.

Escritas monotônicas

Se uma operação de gravação precisar preceder outras operações de gravação, o servidor executará essa operação de gravação primeiro.

Por exemplo, se você chamar insertOne() para inserir um documento e, em seguida, chamar updateOne() para modificar o documento inserido, o servidor executará a operação de inserção primeiro.

Escritas que seguem as leituras

Se uma operação de gravação precisar seguir outras operações de leitura, o servidor executará primeiro as operações de leitura.

Por exemplo, se você chamar findOne() para recuperar um documento e, em seguida, chamar deleteOne() para excluir o documento recuperado, o servidor executará primeiro a operação de localização.

Dica

Para saber mais sobre os conceitos mencionados nesta seção, consulte as seguintes entradas de manual do MongoDB Server :

O driver fornece duas APIs para realizar transações, a API Principal e a API de Transações Convenientes.

A API principal é uma estrutura que permite criar, confirmar e encerrar transações. Ao usar esta API, você deve executar explicitamente as seguintes ações:

  • Crie, confirme e encerre a transação.

  • Crie e finalize a sessão na qual você executa a transação.

  • Implemente lógica de tratamento de erros.

A Convenient Transaction API é uma estrutura que permite que você execute transações sem ser responsável por confirmá-las ou encerrá-las. Essa API incorpora automaticamente a lógica de tratamento de erros para tentar novamente as operações quando o servidor gera determinados tipos de erro. Para saber mais sobre esse comportamento, consulte a seção Erros de transação deste guia.

Importante

Quando você se conecta ao MongoDB Server versão 4.2 ou anterior, você pode executar operações de gravação em uma transação somente em coleções que já existem. Quando você se conecta ao MongoDB Server versão 4.4 e posterior, o servidor cria automaticamente coleções conforme necessário quando você executa operações de gravação em uma transação. Para saber mais sobre esse comportamento, consulte Criar coleções e índices em uma transação no manual do servidor.

A API central fornece os seguintes métodos para implementar transações:

Você deve executar as seguintes etapas ao usar esta API:

  • Passe a instância de sessão para cada operação que deseja executar nessa sessão.

  • Implemente um bloco catch no qual você identifica erros de transação do servidor e implementa a lógica de tratamento de erros.

O código a seguir demonstra como realizar uma transação usando a API Central:

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

Usar uma Sessão com o Cliente Que a Iniciou

O driver lançará um erro se você fornecer uma sessão de uma instância de MongoClient para uma instância de cliente diferente.

Por exemplo, o código a seguir gera um erro MongoInvalidArgumentError porque cria uma instância ClientSession do cliente client1, mas fornece essa sessão ao cliente client2 para uma operação de gravação:

const session = client1.startSession();
client2.db('myDB').collection('myColl').insertOne({ name: 'Jane Eyre' }, { session });

Dica

Gerenciamento explícito de recursos

O driver Node.js suporta nativamente o gerenciamento explícito de recursos MongoClient ClientSessionpara,, ChangeStreams e cursores. Este recurso é experimental e sujeito a alterações. Para saber como usar o gerenciamento explícito de recursos, consulte as Notas de versão do v.6.9

Para ver um exemplo totalmente executável que usa essa API, consulte o exemplo de uso Usar a Core API .

A API de transação conveniente oferece os seguintes métodos para implementar transações:

  • withSession(): Executa a chamada de resposta passada em uma sessão. A API cuida da criação e do encerramento da sessão automaticamente.

  • withTransaction(): Executa a chamada de resposta passada a ela dentro de uma transação e chama o commitTransaction() método quando a chamada de resposta retorna.

Esses métodos retornam o valor que o retorno de chamada retorna. Por exemplo, se um retorno de chamada que você passar para o método withTransaction() retornar o documento { hello: "world" }, então o método withTransaction() também retornará esse documento.

Importante

Para evitar erros de loop infinito, certifique-se de que a chamada de resposta de resposta que você passa para o método withTransaction() capture todos os erros que ela gera.

Ao usar a API de transação conveniente, você pode propagar os valores de retorno da chamada de resposta como os valores de retorno dos métodos withTransaction() e withSession() para trabalhar com eles em outras partes do seu código.

Você deve executar as seguintes etapas ao usar esta API:

  • Passe a instância de sessão para cada operação que deseja executar nessa sessão.

  • Implemente a sintaxe assíncrona await para cada operação na sessão.

  • Evite paralelismo, como chamar o método Promise.all(). Usar sessões em paralelo geralmente leva a erros no servidor.

O código a seguir demonstra como realizar uma transação usando a API de Transação Conveniente:

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 um exemplo totalmente executável que usa essa API, consulte o exemplo de uso API de transação conveniente.

Observação

Operações paralelas não suportadas

O driver Node.js não suporta a execução de operações paralelas dentro de uma única transação.

Você pode passar uma instância TransactionOptions para os métodos startTransaction() e withTransaction() para configurar como o driver executa uma transação. Quando você especifica uma opção, ela substitui o valor da opção que você pode ter definido em sua instância MongoClient .

A tabela seguinte inclui opções que você pode especificar em uma instância do TransactionOptions :

Contexto
Descrição

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 o tempo de execução de uma ação de confirmação em uma transação, em milissegundos.

Para obter uma lista completa de opções, consulte a documentação da API para TransactionOptions.

Observação

A transação herda as configurações de sua instância MongoClient , a menos que você as especifique em suas opções de transação.

O código a seguir mostra como definir e passar as opções de transação para o método startTransaction():

const txnOpts = {
readPreference: 'primary',
readConcern: { level: 'local' },
writeConcern: { w: 'majority' },
maxCommitTimeMS: 1000
};
session.startTransaction(txnOpts);

Como as transações do MongoDB são compatíveis com ACID, o driver pode produzir erros durante a operação para garantir que seus dados permaneçam consistentes. Se ocorrerem os seguintes erros, seu aplicação deverá tentar novamente a transação:

  • TransientTransactionError: gerado se uma operação de gravação encontrar um erro antes do driver confirmar a transação. Para saber mais sobre esse tipo de erro, consulte a Descrição do TransientTransactionError na página API de Drivers no manual do Servidor.

  • UnknownTransactionCommitResult: Criado se a operação de commit encontrar um erro. Para saber mais sobre esse tipo de erro, consulte a Descrição do UnknownTransactionCommitResult na página API de Drivers no manual do Servidor.

As seções a seguir descrevem como lidar com esses erros ao usar APIs diferentes.

A Convenient Transaction API incorpora a lógica de repetição para esses tipos de erro. O driver tenta novamente a transação automaticamente até que haja uma confirmação bem-sucedida.

Se você estiver usando a API Central para executar uma transação, deverá adicionar as seguintes funções de tratamento de erros ao seu aplicação:

  • Uma função que tenta novamente toda a transação quando o motorista encontra um TransientTransactionError

  • Uma função que tenta novamente a operação de confirmação quando o motorista encontra um UnknownTransactionCommitResult

Essas funções devem ser executadas até que haja uma confirmação bem-sucedida ou um erro diferente. Para obter um exemplo dessa lógica de repetição, consulte a seção API principal na página API drivers no manual do servidor.

Voltar

Operações compostas

Nesta página