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

Transações

Nesta página

  • API de transações
  • Transações e Atomicidade
  • Transações e Operações
  • Transações e Sessões
  • Read Concern/Write Concern/Preferência de leitura
  • Informações gerais
  • Saiba mais

No MongoDB, uma operação em um único documento é atômica. Como é possível usar documentos e arrays incorporados para capturar relacionamentos entre dados em uma única estrutura de documento, em vez de normalizar vários documentos e collections, essa atomicidade de documento único evita a necessidade de transações distribuídas para muitos casos de uso práticos.

Para situações que exigem atomicidade de leituras e gravações em vários documentos (em uma collection única ou múltipla), o MongoDB suporta transações distribuídas. Com transações distribuídas, as transações podem ser usadas em diversas operações, collections, bancos de dados, documentos e shards.


➤ Use o menu suspenso Selecione a linguagem no canto superior direito para definir a linguagem do exemplo a seguir.


Dica

Veja também:

Para ver um exemplo em mongosh, consulte o exemplomongosh .

Para situações que exigem atomicidade de leituras e escritos em vários documentos (em uma única coleção ou várias coleções), o MongoDB suporta transações distribuídas, incluindo transações em conjuntos de réplicas e clusters fragmentados.

As transações distribuídas são atômicas:

  • As transações aplicam todas as alterações de dados ou revertem as alterações.

  • Se uma transação for confirmada, todas as alterações de dados feitas na transação serão salvas e ficarão visíveis fora da transação.

    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 é abortada, todas as alterações de dados feitas na transação são descartadas sem nunca se tornarem visíveis. Por exemplo, se operação na transação falhar, a transação será abortada e todas as alterações de dados feitas na transação serão descartadas sem que se tornem visíveis.

Importante

Na maioria dos casos, uma transação distribuída incorre em um custo de desempenho maior do que as gravações de um único documento, e a disponibilidade de transações distribuídas não deve substituir o design eficaz do esquema. Em muitos cenários, o modelo de dados desnormalizado (documentos e arrays incorporados) continuará a ser ideal para seus dados e casos de uso. Ou seja, para muitos cenários, modelar seus dados adequadamente minimizará a necessidade de transações distribuídas.

Para considerações adicionais sobre o uso de transações (como limite de tempo de execução e limite de tamanho do oplog), consulte também Considerações de produção.

Transações distribuídas podem ser usadas em várias operações, collections, bancos de dados, documentos e shards.

Para transações:

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

Para obter uma lista de operações sem suporte em transações, consulte Operações restritas.

Dica

Ao criar ou descartar uma coleta imediatamente antes de iniciar uma transação, se a coleta for acessada dentro da transação, emita a operação de criação ou entrega em espera com write concern "majority" para garantir que a transação possa adquirir os bloqueios necessários.

É possível executar as seguintes operações em uma transação distribuída quando a transação não é uma transação de gravação entre fragmentos:

  • Criar coleções

  • Crie índices na nova coleta vazia criada anteriormente na mesma transação.

Ao criar uma coleta dentro de uma transação:

Ao criar um índice dentro de uma transação [1], o índice a ser criado deve estar em:

  • uma coleção inexistente. A coleção é criada como parte da operação.

  • uma nova coleta vazia criada anteriormente na mesma transação.

[1] Você também pode executar db.collection.createIndex() e db.collection.createIndexes() em índices existentes para verificar a existência. Estas operações retornam com sucesso sem criar o índice.
  • 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 usar a etapa $graphLookup dentro de uma transação enquanto segmenta uma coleção fragmentada.

  • Para a criação explícita de uma collection ou de um índice em uma transação, o nível de read concern da transação deve ser "local".

    Para criar coleções e índices explicitamente, use os seguintes comandos e métodos:

    Comando
    Método
    create

Dica

Veja também:

Para realizar uma operação de contagem dentro de uma transação, use o estágio de agregação $count ou o estágio de agregação $group (com uma expressão $sum de agregação.

Os drivers do MongoDB fornecem uma API de collection countDocuments(filter, options) como um método auxiliar que usa o $group com uma expressão $sum para executar uma contagem. A API count() está obsoleta.

mongosh fornece o método auxiliar db.collection.countDocuments() que usa o $group com uma expressão $sum para executar uma contagem.

Para realizar uma operação distinta dentro de uma transação:

  • Para coleções não fragmentadas, você pode usar o db.collection.distinct() método /o distinct comando , bem como o pipeline de agregação com o estágio $group .

  • Para coleções fragmentadas, você não pode utilizar o método db.collection.distinct() ou o comando distinct.

    Para localizar os valores distintos para uma coleção fragmentada, use o pipeline de agregação com o estágio $group. Por exemplo:

    • Em vez de db.coll.distinct("x"), use

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

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

    O pipeline retorna um cursor para um documento:

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

    Itere o cursor para acessar o documento de resultados.

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 seguintes operações não são permitidas nas transações:

  • As transações são associadas a uma sessão.

  • Você pode ter no máximo uma transação aberta por vez em uma sessão.

  • Ao utilizar os drivers, cada operação da transação deve ser associada à sessão. Consulte a documentação específica do seu driver para obter detalhes.

  • Se uma sessão terminar e houver uma transação aberta, a transação será abortada.

As operações em uma transação usam a preferência de leituraem nível de transação.

Usando os drivers, você pode definir a preferência de leitura no nível da transação no início da transação:

  • Se a preferência de leitura no nível da transação não estiver definida, a transação usará a preferência de leitura no nível da sessão.

  • Se a read preference da transação e da sessão não estiver definida, a transação usará a read preference do cliente. Por padrão, a read preference do cliente é primary.

Transações distribuídas que contêm operações de leitura devem utilizar a read preference primary. Todas as operações em uma determinada transação devem ser roteadas para o mesmo membro.

As operações em uma transação usam preocupação de leitura no nível da transação. Isso significa que uma preocupação de leitura definida no nível da coleção e do banco de dados é ignorada na transação.

Você pode definir a preocupação de leitura no nível da transação no início da transação.

  • Se a preocupação de leitura no nível da transação não estiver definida, a preocupação de leitura no nível da transação será padronizada para a preocupação de leitura no nível da sessão.

  • Se a preocupação de leitura no nível da transação e no nível da sessão não estiverem definidos, a preocupação de leitura no nível da transação será padronizada para a preocupação de leitura no nível do cliente. Por padrão, a preocupação de leitura no nível do cliente é "local" para leituras no primário. Veja também:

As transações suportam os seguintes níveis de preocupação de leitura:

  • A preocupação de leitura "local" retorna os dados mais recentes disponíveis no nó, mas pode ser revertida.

  • Para transações em cluster fragmentado, a preocupação de leitura "local" não pode garantir que os dados sejam da mesma visualização de snapshot nos fragmentos. Se o isolamento de snapshot for necessário, utilize a preocupação de leitura do "snapshot" .

  • Você pode criar collections e índices dentro de uma transação. Se criar explicitamente uma collection ou um índice, a transação deverá usar a read concern "local". Se você criar implicitamente uma coleção, poderá usar qualquer uma das read concerns disponíveis para transações.

  • Se a transação for confirmada com a write concern "maioria", a read concern "majority" retornará dados que foram reconhecidos pela maioria dos membros do conjunto de réplicas e não podem ser revertidos. Caso contrário, a read concern "majority" não garante que as operações de leitura lerão dados confirmados pela maioria.

  • Para transações em cluster fragmentado, a preocupação de leitura "majority" não pode garantir que os dados sejam da mesma visualização de snapshot nos fragmentos. Se o isolamento de snapshot for necessário, use a read concern "snapshot".

  • Preocupação de leitura "snapshot" retorna dados de um snapshot de dados comprometidos majoritariamente se a transação for confirmada com a preocupação de gravação na "maioria".

  • Se a transação não usar a write concern na "maioria" para a confirmação, a preocupação "snapshot" leitura não fornecerá nenhuma garantia de que as operações de leitura usaram um snapshot de dados confirmados pela maioria .

  • Para transações em clusters fragmentados, a visualização "snapshot" dos dados é sincronizada entre fragmentos.

As transações usam a preocupação de gravação em nível de transação para confirmar as operações de gravação As operações de gravação dentro das transações devem ser executadas sem uma especificação explícita de preocupação de gravação e usar a preocupação de gravação padrão. No momento de confirmação, as gravações são confirmadas usando a preocupação de gravação no nível da transação.

Dica

Não defina explicitamente a preocupação de gravação para as operações individuais de gravação dentro de uma transação. Definir preocupações de gravação para operações de gravação individuais dentro de uma transação retorna um erro.

Você pode definir a write concern no nível da transação no início da transação:

  • Se a preocupação de gravação no nível da transação não estiver definida, a preocupação de gravação no nível da transação será padronizada para a preocupação de gravação no nível da sessão para o commit.

  • Se a preocupação de gravação no nível da transação e a preocupação de gravação no nível da sessão não estiverem definidas, a preocupação de gravação no nível da transação será padronizada para a preocupação de gravação no nível do cliente de:

As transações suportam todos os valores w de preocupação de gravação, incluindo:

  • A preocupação de gravação w: 1 retorna a confirmação após a confirmação ter sido aplicada ao primário.

    Importante

    Quando você confirma comw: 1, sua transação pode ser revertida se houver um failover.

  • Quando você confirma comw: 1 write concern, a preocupação de leitura de "majority" no nível da transação não fornece garantias de que as operações de leitura na transação leiam os dados confirmados pela maioria.

  • Quando você se compromete com a write concern w: 1, read concern "snapshot" no nível da transação não garante que as operações de leitura na transação usaram um snapshot dos dados confirmados pela maioria.

  • A preocupação de gravação w: "majority" retorna a confirmação após a confirmação ter sido aplicada à maioria dos membros votantes.

  • Quando você se compromete com a write concern w: "majority", a read concern "majority" no nível da transação garante que as operações tenham lido os dados confirmados pela maioria. Para transações em cluster fragmentado, esta visualização dos dados comprometidos pela maioria não é sincronizada entre os fragmentos.

  • Quando você se compromete comw: "majority" write concern, a read concern de "snapshot" no nível de transação garante que as operações tenham lido a partir de um snapshot sincronizado de dados confirmados pela maioria.

Observação

Independentemente do write concern especificado para a transação, a operação de confirmação de uma transação de cluster fragmentado inclui algumas partes que usam o write concern {w: "majority", j: true} .

O parâmetro do servidor coordinateCommitReturnImmediatelyAfterPersistingDecision controla quando as decisões feitas na transação são devolvidas ao cliente.

O parâmetro foi introduzido no MongDB 5.0 com um valor padrão de true. No MongoDB 6.1, o valor padrão muda para false.

Quando coordinateCommitReturnImmediatelyAfterPersistingDecision é false, o coordenador de transações do fragmento aguarda que todos os membros confirmem a confirmação de uma transação com vários documentos antes de retornar a decisão de confirmação para o cliente.

Se você especificar uma preocupação de gravação "majority" para uma transação multidocumento e a transação não for replicada para a maioria calculada dos membros do conjunto de réplicas, a transação poderá não ser revertida imediatamente para os membros do conjunto de réplicas. O conjunto de réplicas será eventualmente consistente. Uma transação é sempre aplicada ou revertida para todos os membros do conjunto de réplicas.

Independentemente da write concern especificada para a transação, o driver aplica w: "majority" como a write concern ao tentar novamente commitTransaction.

As seções a seguir descrevem considerações adicionais para transações.

Para transações em ambientes de produção, consulte Considerações de produção. Além disso, para clusters fragmentados, consulte Considerações de produção (clusters fragmentados).

As transações cujas operações de gravação abrangem vários fragmentos gerarão o erro e serão abortadas se qualquer operação de transação ler ou gravar em um fragmento que contenha um árbitro.

Não é possível executar transações em um cluster fragmentado que tenha um shard com writeConcernMajorityJournalDefault definido como false (como um shard com um membro votante que usa o mecanismo de armazenamento na memória).

Observação

Independentemente do write concern especificado para a transação, a operação de confirmação de uma transação de cluster fragmentado inclui algumas partes que usam o write concern {w: "majority", j: true} .

Para obter o status e as métricas da transação, use os seguintes métodos:

Fonte
Devoluções
Retorna métricas de transações.
$currentOp aggregation pipeline

Retorna:

currentOp comando

Retorna:

mongod e mongos mensagens de log
Inclui informações sobre transações lentas (que são transações que excedem o limite deoperationProfiling.slowOpThresholdMs) no componente de log TXN.

Para usar transações, a featureCompatibilityVersion para todos os membros da implantação deve ser pelo menos:

Implantação
Mínimo featureCompatibilityVersion
Conjunto de réplicas
4.0
Cluster fragmentado
4.2

Para verificar o fCV de um membro, conecte-se ao membro e execute o comando:

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

Para mais informações, consulte a página de referência do setFeatureCompatibilityVersion.

As transações distribuídas são compatíveis com conjuntos de réplicas e clusters fragmentados onde:

  • o primário usa o mecanismo de armazenamento WiredTiger e

  • os membros secundários usam o mecanismo de armazenamento WiredTiger ou os mecanismos de armazenamento na memória .

Observação

Você não pode executar transações em um cluster fragmentado que tenha um shard com writeConcernMajorityJournalDefault definido como false, como um shard com um nó votante que use o mecanismo de armazenamento na memória

A partir do MongoDB 5.2 (e 5.0.4):

← update Evento