Todos os produtos
Search
Central de documentação

ApsaraDB for MongoDB:Transações e Read/Write Concern

Última atualização: Jun 26, 2026

Melhores práticas para usar transações e configurar o Read/Write Concern no ApsaraDB for MongoDB.

Contexto

O MongoDB 4.0 introduziu transações independentes (transações de replica set) para operações em uma ou mais coleções dentro de um único replica set. O MongoDB 4.2 adicionou transações distribuídas (transações com sharding) para operações em várias coleções e shards.

No MongoDB, as operações de documento único são sempre atômicas. Os aplicativos podem usar documentos incorporados e arrays para modelar relacionamentos dentro de um único documento, diferentemente dos bancos de dados relacionais, que exigem coleções normalizadas e joins. Com uma modelagem de dados adequada, a atomicidade de documento único elimina a necessidade de transações distribuídas na maioria dos casos.

No entanto, aplicativos financeiros ou contábeis ainda podem exigir transações distribuídas. O MongoDB 4.2 e versões posteriores oferecem suporte total a essa capacidade.

Transações

Informações básicas

As APIs de transação do MongoDB são semelhantes às de bancos de dados relacionais; portanto, a curva de aprendizado é mínima.

O exemplo a seguir demonstra uma transação completa com as APIs startTransaction/abortTransaction/commitTransaction, além das configurações de session e readConcern/writeConcern.

// Create collections.
db.getSiblingDB("mydb1").foo.insertOne(
    {abc: 0},
    { writeConcern: { w: "majority", wtimeout: 2000 } }
)
db.getSiblingDB("mydb2").bar.insertOne(
   {xyz: 0},
   { writeConcern: { w: "majority", wtimeout: 2000 } }
)
// Start a session.
session = db.getMongo().startSession( { readPreference: { mode: "primary" } } );
coll1 = session.getDatabase("mydb1").foo;
coll2 = session.getDatabase("mydb2").bar;
// Start a transaction.
session.startTransaction( { readConcern: { level: "local" }, writeConcern: { w: "majority" } } );
// Perform operations in the transaction.
try {
   coll1.insertOne( { abc: 1 } );
   coll2.insertOne( { xyz: 999 } );
} catch (error) {
   // Abort the transaction if an error occurs.
   session.abortTransaction();
   throw error;
}
// Commit the transaction.
session.commitTransaction();
session.endSession();

Comportamentos principais das transações:

  • Cada transação deve estar associada a uma sessão. Uma sessão suporta apenas uma transação ativa por vez. Encerrar uma sessão reverte qualquer transação ativa.

  • Uma transação distribuída pode abranger vários documentos, coleções e bancos de dados.

  • Uma transação pode ler suas próprias gravações não confirmadas, mas essas gravações não ficam visíveis para operações fora da transação.

  • As gravações não são replicadas para nós secundários até a confirmação da transação. Após a confirmação, as gravações são aplicadas automaticamente a todos os nós secundários.

  • As transações bloqueiam os documentos modificados, impedindo outras operações até a conclusão. Se não for possível adquirir um bloqueio dentro de 5 milissegundos (padrão), a transação é abortada devido a um conflito de gravação. Esse tempo limite é controlado pelo parâmetro maxTransactionLockRequestTimeoutMillis.

  • As transações tentam novamente de forma automática em caso de erros transitórios, como interrupções temporárias de rede. Essa nova tentativa é transparente para o cliente.

  • Uma transação que executa por mais de 60 segundos é abortada à força. Esse tempo limite é controlado pelo parâmetro transactionLifetimeLimitSeconds.

Limites

  • Não é possível criar novas coleções ou índices em uma transação distribuída.

  • Transações não podem gravar em coleções limitadas (capped collections).

  • Transações não podem usar o read concern snapshot para ler de coleções limitadas. Este limite se aplica ao MongoDB 5.0 e versões posteriores.

  • Em uma transação, não é possível ler ou gravar em coleções nos bancos de dados config/admin/local.

  • Transações não podem gravar em coleções do sistema, como coleções no formato system.*.

  • Transações não suportam explain.

  • Não é possível usar getMore dentro de uma transação para ler cursores criados fora dela. Da mesma forma, não é possível usar getMore fora de uma transação para ler cursores criados dentro dela.

  • A primeira operação em uma transação não pode ser um comando como killCursors ou hello.

  • Não é possível executar comandos que não sejam CRUD dentro de uma transação. Exemplos incluem listCollections, listIndexes, createUser, getParameter e count.

  • Para transações distribuídas, não defina o parâmetro writeConcernMajorityJournalDefault nos shards como false.

  • Transações distribuídas não suportam shards com árbitros.

Melhores práticas

Prefira transações independentes em vez de transações distribuídas

Transações distribuídas têm desempenho inferior ao das transações independentes devido à lógica mais complexa. No MongoDB, modelos de dados desnormalizados (documentos incorporados e arrays) continuam sendo a melhor escolha. Com uma modelagem de dados adequada, as transações independentes atendem à maioria dos requisitos transacionais.

Evite transações de longa duração

O MongoDB aborta automaticamente transações distribuídas que executam por mais de 60 segundos. Divida transações grandes em partes menores e garanta que as consultas usem índices adequados para execução rápida.

Evite modificar muitos documentos em uma única transação

Embora não haja um limite rígido para documentos lidos em uma transação, modificar muitos documentos aumenta a carga de sincronização entre primário e secundário, podendo causar atraso na replicação. Limite as modificações a 1.000 documentos por transação. Para lotes maiores, divida em várias transações.

Evite transações grandes que excedam 16 MB

No MongoDB 4.0, uma transação usa uma única entrada de oplog limitada a 16 MB. Operações de atualização armazenam alterações incrementais; inserções armazenam documentos completos. Se o oplog combinado exceder 16 MB, a transação será abortada e revertida.

O MongoDB 4.2 e versões posteriores podem dividir as gravações da transação em várias entradas de oplog, removendo o limite de 16 MB por entrada única. No entanto, mantenha o tamanho das transações dentro de 16 MB para evitar outros problemas.

Trate as reversões de transação no cliente

Quando uma transação é abortada, ela retorna uma exceção e é revertida. Seu aplicativo deve capturar essas exceções e tentar novamente em caso de erros transitórios (alternância entre primário/secundário, falha de nó). Embora os drivers do MongoDB tentem novamente as confirmações automaticamente via Retryable Writes, o aplicativo ainda precisa tratar erros não repetíveis, como TransactionTooLarge, TransactionTooOld e TransactionExceededLifetimeLimitSeconds.

Evite operações DDL em transações

Operações DDL, como createIndex ou dropDatabase, são bloqueadas por transações ativas no mesmo banco de dados ou coleção. Operações DDL bloqueadas impedem que novas transações adquiram bloqueios, causando sua interrupção.

O MongoDB 4.4 flexibilizou essas restrições por meio do parâmetro shouldMultiDocTxnCreateCollectionAndIndexes. É possível executar createCollection ou createIndex em uma transação distribuída, com as seguintes limitações:

  • Coleções só podem ser criadas implicitamente.

  • A coleção de destino não deve existir previamente.

  • A coleção de destino deve estar vazia.

Portanto, evite operações DDL em transações.

Reverta prontamente transações não confirmadas ou com erro

Modificações de transações não confirmadas residem no cache do WiredTiger. Várias transações simultâneas não confirmadas ou com erro podem sobrecarregar o cache e causar problemas adicionais. Reverta transações desnecessárias o mais rápido possível para liberar recursos.

Aumente o tempo limite de bloqueio se as transações forem revertidas frequentemente

Por padrão, uma operação de transação é revertida se não conseguir adquirir um bloqueio dentro de 5 milissegundos. Os bloqueios são liberados na confirmação ou reversão. Se os tempos limite de bloqueio causarem reversões frequentes, aumente o parâmetro maxTransactionLockRequestTimeoutMillis.

Se aumentar o tempo limite não resolver, verifique se há operações que mantêm bloqueios por períodos prolongados, como operações DDL ou consultas não otimizadas, e otimize-as.

Evite modificações simultâneas no mesmo documento dentro e fora de uma transação

Se uma gravação externa modificar um documento que uma transação em andamento também está modificando, a transação será revertida devido a um conflito de gravação. Por outro lado, se uma transação já mantiver um bloqueio em um documento, as gravações externas nesse documento aguardarão até que a transação seja concluída.

Em caso de conflito de gravação, a gravação externa não falha. O MongoDB tenta novamente internamente, incrementando o contador writeConflicts até obter sucesso. O cliente percebe uma operação bem-sucedida, porém mais lenta.

Um pequeno número de conflitos de gravação tem impacto mínimo. Conflitos frequentes degradam o desempenho. Use logs de auditoria ou logs de consultas lentas para detectar conflitos excessivos de gravação.

Riscos de bugs no kernel

Transações de longa duração ou superdimensionadas colocam uma carga significativa no cache do WiredTiger. Desde o início da transação não confirmada mais antiga, o WiredTiger precisa manter dados e estado para todas as gravações subsequentes. Transações ativas compartilham o mesmo snapshot, então novas gravações se acumulam no cache durante toda a vida útil da transação e não podem ser removidas até que a transação seja confirmada ou abortada. Um cache sobrecarregado (uso e uso sujo excedendo os limiares) causa travamentos no banco de dados, aumento de latência, utilização total da CPU e possíveis deadlocks. Problemas relacionados: SERVER-50365 e SERVER-51281.

O ApsaraDB for MongoDB recomenda atualizar para o MongoDB 5.0 ou posterior para aplicativos que utilizam transações intensivamente.

Read Concern

Informações básicas

O Read Concern controla a consistência e o isolamento com os seguintes níveis:

  • "local": Padrão para leituras em nós primários ou secundários. Lê do nó local e pode retornar dados que serão revertidos posteriormente.

  • "available": Padrão para leituras em secundários em um cluster com sharding. Pode retornar dados que serão revertidos posteriormente. Não verifica a versão do shard e pode retornar documentos órfãos. Oferece a menor latência de acesso.

  • "majority": Lê dados reconhecidos pela maioria dos membros do replica set. Esses dados não serão revertidos.

  • "linearizable": O nível mais rigoroso. Aguarda até que todas as gravações anteriores sejam reconhecidas pela maioria dos nós. Menor desempenho; disponível apenas no primário.

  • "snapshot": Lê de um snapshot de dados reconhecido pela maioria dos nós. Pode ser associado a um ponto específico no tempo usando atClusterTime.

Notas de uso:

  • Os dados mais recentes em um único nó mongod não representam necessariamente os dados mais recentes do replica set, independentemente do nível de Read Concern.

  • É possível especificar diferentes níveis de Read Concern por operação. O MongoDB 4.4+ também suporta um padrão no servidor, substituído pelas configurações no nível da operação.

  • O Read Concern é ignorado ao ler do banco de dados local. Todos os dados no banco de dados local são legíveis independentemente do nível.

  • Transações distribuídas suportam apenas três níveis de Read Concern: "local", "majority" e "snapshot".

  • Sessões causalmente consistentes devem usar o nível de Read Concern "majority".

Melhores práticas

Para transações distribuídas, defina o Read Concern para a transação, não para operações individuais

Especifique o Read Concern no nível da transação. A configuração no nível da transação substitui quaisquer outras configurações ou padrões de Read Concern.

O Read Concern se aplica a qualquer consulta de banco de dados, seja uma leitura de documento único, uma leitura de vários documentos ou parte de uma transação.

Use o nível de Read Concern "majority" para casos de uso gerais

Defina o Read Concern como "majority" para garantir isolamento e consistência. Isso assegura que o aplicativo leia apenas dados replicados para a maioria dos nós, evitando reversão na eleição do primário.

Para cenários de 'Ler Suas Próprias Gravações', leia do primário e use o nível de Read Concern "local" ou "linearizable"****

Leia do nó primário com Read Concern "local" ou "linearizable". Se o Write Concern for "majority", você também pode usar o Read Concern "majority".

O MongoDB 3.6+ também suporta sessões causalmente consistentes para este cenário.

Para cenários que exigem a maior consistência, use o Read Concern "linearizable" com um tempo limite maxTimeMS****

O nível "linearizable" confirma que o nó ainda é o primário e que os dados retornados não serão revertidos. No entanto, isso impacta significativamente a latência. Use-o com um tempo limite maxTimeMS para evitar bloqueio indefinido caso a maioria dos nós fique indisponível.

Write Concern

Informações básicas

O Write Concern usa o seguinte formato. Referência completa: Write Concern.

{ w: <value>, j: <boolean>, wtimeout: <number> }
  • O Write Concern controla as garantias de persistência de dados nestes níveis:

    • {w: 0}: Sem reconhecimento. Não confirma a conclusão; pode ocorrer perda de dados.image

    • {w: 1}: Reconhece a gravação na memória. Padrão antes do MongoDB 5.0. Ainda pode ocorrer perda de dados porque os dados ainda não foram persistidos em disco.image

    • {j: true}: Reconhecimento de journal. Confirma que a gravação foi liberada para o log de gravação antecipada (WAL) no armazenamento persistente. A gravação não será perdida.image

    • { w: "majority" }: Reconhecimento pela maioria. Padrão para MongoDB 5.0+. Aguarda a replicação da gravação para a maioria dos nós. Os dados não serão revertidos.image

    • Reconhecimento por réplica: Aguarda a replicação para um número especificado de nós antes de reconhecer.

    • Reconhecimento personalizado: É possível usar o parâmetro settings.getLastErrorModes para especificar outros métodos de reconhecimento personalizados usando tags.

Notas de uso:

  • É possível especificar o Write Concern para qualquer operação de gravação ou transação. Se omitido, o padrão será usado.

    Nota

    No MongoDB 5.0+, o Write Concern global padrão para um replica set padrão de três membros mudou de {w:1} para {w:"majority"}. Isso pode causar degradação de desempenho após a atualização.

  • Nós ocultos, nós atrasados e outros nós votantes com prioridade 0 em um replica set podem contar para um reconhecimento "majority".

  • É possível especificar diferentes níveis de Write Concern por operação. O MongoDB 4.4+ também suporta um padrão no servidor, substituído pelas configurações no nível da operação.

  • Ao gravar no banco de dados local, qualquer Write Concern especificado é ignorado.

  • Sessões causalmente consistentes devem usar o Write Concern "majority".

Melhores práticas

Para transações distribuídas, defina o Write Concern para a transação, não para operações individuais

Definir um Write Concern para operações de gravação individuais dentro de uma transação retorna um erro.

Use o Write Concern "majority" para casos de uso gerais

O Write Concern "majority" garante que a maioria dos nós do replica set reconheça a gravação, evitando perda de dados ou reversão mesmo durante falhas de nó ou alternâncias inesperadas.

Para cenários de gravação intensiva, considere usar {w:1} e monitore o atraso de replicação dos nós secundários

{w:1} oferece melhor desempenho de gravação para cenários com muitas gravações. No entanto, monitore o atraso de replicação dos nós secundários. Atrasos excessivos podem fazer com que o primário entre em estado de ROLLBACK. Se o atraso exceder o período de retenção do oplog, os secundários entram em um estado de RECOVERING que requer intervenção manual.

Ao carregar dados em lote ou realizar migração DTS em uma instância ApsaraDB for MongoDB executando uma versão anterior à 5.0, use o Write Concern "majority" se ocorrer atraso excessivo.

Defina o Write Concern mais adequado para diferentes operações

É possível definir o Write Concern por operação. Por exemplo, use transações com um Write Concern específico para dados financeiros para garantir atomicidade, "majority" para dados principais de jogadores para evitar reversão, e o padrão ou {w:1} para dados de log.

O MongoDB oferece essa flexibilidade para que os aplicativos escolham as configurações apropriadas com base em seus requisitos.

Referências