Menu Docs
Página inicial do Docs
/ / /
Controlador Node.js
/

Transações

Nesta página

  • Visão geral
  • APIs de transações
  • Core API
  • API de transação conveniente
  • opções de transação
  • Erros de transação

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.

No MongoDB, transações de vários documentos são executadas dentro de uma sessão de cliente. Uma sessão de cliente é um agrupamento de operações de leitura ou escrita relacionadas que você deseja executar sequencialmente. Recomendamos que você reutilize seu cliente para várias sessões e transações, em vez de fazer a instância de um novo cliente a cada vez.

Quando combinado com majority preocupações de leitura e gravação, o driver garante a consistência causal entre as operações. Para saber mais, consulte Sessões de cliente e garantias de consistência causal 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 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 });

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 lida com a criação e o encerramento da sessão automaticamente.

  • withTransaction(): Executa a chamada de resposta passada a ela dentro de uma transação e chama o método commitTransaction() 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);

Se você estiver usando a API Central para executar uma transação, deverá incorporar a lógica de tratamento de erros em seu aplicativo para os seguintes erros:

  • TransientTransactionError: gerado se uma operação de gravação falhar antes do driver confirmar a transação. Para saber mais sobre esse erro, consulte a descrição TransientTransactionError na página API do Driver no manual do servidor.

  • UnknownTransactionCommitResult: Criado se a operação de confirmação encontrar um erro. Para saber mais sobre esse erro, consulte a descrição UnknownTransactionCommitResult na página API do driver no manual do servidor.

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

Voltar

Agregação