Menu Docs

Página inicial do DocsDesenvolver aplicaçõesManual do MongoDB

Considerações de produção

Nesta página

  • Disponibilidade
  • Compatibilidade de recursos
  • Limite de tempo de execução
  • Limite de tamanho do Oplog
  • Cache do WiredTiger
  • Transações e segurança
  • Restrição de configuração de fragmento
  • Clusters fragmentados e árbitros
  • Adquirindo travas
  • Operações e Transações DDL Pendentes
  • Transações em andamento e conflitos de gravação
  • Transações em andamento e leituras obsoletas
  • Transações em andamento e migração de chunk
  • Leituras Externas Durante a Confirmação
  • Erros
  • Informações adicionais

A página a seguir lista algumas considerações de produção para a execução de transações. Eles se aplicam se você executa transações em conjuntos de réplicas ou clusters fragmentados. Para executar transações em cluster fragmentado, consulte também Considerações de produção ( cluster fragmentado) para obter considerações adicionais específicas do cluster fragmentado.

  • Na versão 4,0, o MongoDB suporta transações de vários documentos em conjuntos de réplicas.

  • Na versão 4.2, o MongoDB introduz transações distribuídas, que adiciona suporte para transações de vários documentos em clusters fragmentados e incorpora o suporte existente para transações de vários documentos em conjuntos de réplicas.

    Para usar transações em implantações do MongoDB 4.2 (conjuntos de réplica e clusters fragmentados), os clientes devem usar drivers do MongoDB atualizados para MongoDB 4.2.

Observação

Transações distribuídas e transações multidocumentos

A partir do MongoDB 4.2, os dois termos são sinônimos. Transações distribuídas referem-se a transações multidocumentos em clusters fragmentados e conjuntos de réplicas. As transações multidocumentos (seja em clusters fragmentados ou conjuntos de réplicas) também são conhecidas como transações distribuídas a partir do MongoDB 4.2.

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.

Por padrão, uma transação deve ter um tempo de execução inferior a um minuto. Você pode modificar este limite utilizando transactionLifetimeLimitSeconds para as instâncias do mongod. Para agrupamentos fragmentados, o parâmetro deve ser modificado para todos os membros do conjunto de réplica de fragmento. As transações que excederem esse limite serão consideradas expiradas e serão abortadas por um processo de limpeza periódico.

Para agrupamentos fragmentados, você também pode especificar um limite do maxTimeMS no commitTransaction. Para mais informações, consulte Limite de Tempo de Transações de Clusters Compartilhados.

A partir da versão 4.2,
O MongoDB cria quantas entradas de oplog forem necessárias para encapsular todas as operações de gravação em uma transação, em vez de uma única entrada para todas as operações de gravação na transação. Isso remove o limite de tamanho total de 16 MB para uma transação imposta pela entrada única do oplog para todas as suas operações de gravação. Embora o limite de tamanho total tenha sido removido, cada entrada do oplog ainda deve estar dentro do limite de tamanho do documento BSON de 16 MB.
Na versão 4,0,
O MongoDB cria uma única entrada no oplog (registro de operações) no momento do commit se a transação contiver operações de gravação. Ou seja, as operações individuais nas transações não têm uma entrada de oplog correspondente. Em vez disso, uma única entrada de oplog contém todas as operações de gravação dentro de uma transação. A entrada do oplog da transação deve estar dentro do limite de tamanho do documento BSON de 16 MB.

Para evitar que a pressão do cache de armazenamento afete negativamente o desempenho:

  • Ao abandonar uma transação, interrompa a transação.

  • Quando você encontra um erro durante a operação individual na transação, cancele e tente novamente a transação.

O transactionLifetimeLimitSeconds também garante que as transações expiradas sejam abortadas periodicamente para aliviar a pressão do cache de armazenamento.

Observação

Se você tiver uma transação não acordada que cause pressão excessiva no cache WiredTiger, a transação cancelará e retornará um erro de conflito de escrita.

Se uma transação for muito grande para caber no cache WiredTiger, a transação será anulada e retornará um erro TransactionTooLargeForCache .

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

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.

Por padrão, as transações esperam até 5 milissegundos para adquirir as travas exigidas pelas operações na transação. Se a transação não puder adquirir suas travas necessárias dentro dos 5 milissegundos, a transação será cancelada.

As transações liberam todos os bloqueios ao serem abortadas ou confirmadas.

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.

Você pode usar o parâmetro maxTransactionLockRequestTimeoutMillis para ajustar quanto tempo as transações esperam para adquirir travas. O aumento de maxTransactionLockRequestTimeoutMillis permite que as operações nas transações esperem o tempo especificado para adquirir as travas necessárias. Isso pode ajudar a evitar abortos de transações em aquisições simultâneas momentâneas de travas, como operações de metadados de execução rápida. No entanto, isso poderia atrasar o aborto das operações de transação em impasse.

Você também pode usar o tempo limite específico da operação definindo maxTransactionLockRequestTimeoutMillis como -1.

Se uma transação de vários documentos estiver em andamento, novas operações DDL que afetam o(s) mesmo(s) banco(s) de dados ou collection(ões) aguardam atrás da transação. Embora essas operações DDL pendentes existam, novas transações que acessam o(s) mesmo(s) banco(s) de dados ou coleção(ões) que as operações DDL pendentes não podem obter os travas necessárias e serão abortadas após a esperamaxTransactionLockRequestTimeoutMillis. Além disso, novas operações não transacionais que acessam o(s) mesmo(s) banco(s) de dados ou coleção(ões) serão bloqueadas até que atinjam seu limite maxTimeMS.

Considere os seguintes cenários:

Operação DDL que requer uma trava de collection

Enquanto uma transação em andamento executa várias operações CRUD na collection employees no banco de dados hr, um administrador emite a operação DDL db.collection.createIndex() na collection employees. createIndex() requer uma trava de collection exclusiva na collection.

Até que a transação em andamento seja concluída, a operação createIndex() deve aguardar para obter a trava. Qualquer nova transação que afete a collection employees e seja iniciada enquanto o createIndex() estiver pendente deve aguardar até que createIndex() seja concluída.

A operação DDL createIndex() pendente não afeta as transações em outras collections no database hr. Por exemplo, uma nova transação na contractors collection no hr banco de dados pode ser iniciada e concluída normalmente.

Operação DDL que requer um bloqueio de banco de dados

Enquanto uma transação em andamento executa várias operações CRUD na collection employees no banco de dados hr, um administrador emite a operação DDL collMod na collection contractors no mesmo banco de dados. collMod requer uma trava de banco de dados no banco de dados hr principal.

Até que a transação em andamento seja concluída, a operação collMod deve aguardar para obter a trava. Qualquer nova transação que afete o database hr ou qualquer uma de suas collections e seja iniciada enquanto collMod estiver pending deverá aguardar até a completes de collMod.

Em qualquer um dos cenários, se a operação DDL permanecer pendente por mais de maxTransactionLockRequestTimeoutMillis, as transações pendentes que aguardam essa operação serão canceladas. Ou seja, o valor de maxTransactionLockRequestTimeoutMillis deve cobrir pelo menos o tempo necessário para que a transação em andamento e a operação DDL pendente sejam concluídas.

Dica

Veja também:

  • Transações em andamento e conflitos de gravação

  • Transações em andamento e leituras obsoletas

  • Quais comandos administrativos bloqueiam um banco de dados?

  • Quais comandos administrativos bloqueiam uma collection?

Se uma transação estiver em andamento e uma gravação fora da transação modificar um documento que uma operação na transação tente modificar posteriormente, a transação será interrompida devido a um conflito de escrita.

Se uma transação estiver em andamento e tiver usado uma trava para modificar um documento, quando uma gravação fora da transação tentar modificar o mesmo documento, a gravação aguardará até que a transação termine.

As operações de leitura dentro de uma transação podem retornar dados antigos, conhecidos como leitura obsoleta. Não é garantido que as operações de leitura dentro de uma transação vejam as gravações realizadas por outras transações confirmadas ou gravações não transacionais. Por exemplo, considere a seguinte sequência:

  1. Uma transação está em andamento.

  2. Uma escrita fora da transação exclui um documento.

  3. Uma operação de leitura dentro da transação pode ler o documento agora excluído, pois a operação usa um instantâneo anterior à operação de gravação.

Para evitar leituras obsoletas dentro de transações para um único documento, você pode usar o método db.collection.findOneAndUpdate() . O exemplo mongosh a seguir demonstra como você pode usar o db.collection.findOneAndUpdate() para usar um bloqueio de escrita e garantir que suas leituras estejam atualizadas:

1
db.getSiblingDB("hr").employees.insertOne(
{ _id: 1, status: "Active" }
)
2
session = db.getMongo().startSession( { readPreference: { mode: "primary" } } )
3
session.startTransaction( { readConcern: { level: "snapshot" }, writeConcern: { w: "majority" } } )
employeesCollection = session.getDatabase("hr").employees
4
employeeDoc = employeesCollection.findOneAndUpdate(
{ _id: 1, status: "Active" },
{ $set: { lockId: ObjectId() } },
{ returnNewDocument: true }
)

Observe que, dentro da transação, a operação findOneAndUpdate define um novo campo lockId . Você pode definir o campo lockId para qualquer valor, desde que modifique o documento. Ao atualizar o documento, a transação adquire uma trava.

Se uma operação fora da transação tentar modificar o documento antes de confirmar a transação, o MongoDB retornará um erro de conflito de gravação para a operação externa.

5
session.commitTransaction()

Depois de confirmar a transação, o MongoDB libera a trava.

Observação

Se qualquer 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 na coleção.

A migração de chunk adquire travas de collection exclusivas em alguns estágios.

Se uma transação em andamento tiver um bloqueio em uma collection e uma migração de partes que envolva o início dessa collection, esses estágios de migração deverão aguardar que a transação libere os bloqueios na collection, impactando assim o desempenho das migrações de chunks.

Se uma migração de chunk se intercalar com uma transação (por exemplo, se uma transação for iniciada enquanto uma migração de chunk já estiver em andamento e a migração for concluída antes que a transação trave a collection), a transação será interrompida durante a confirmação e será cancelada.

Dependendo de como as duas operações se intercalam, alguns exemplos de erros incluem (as mensagens de erro foram abreviadas):

  • an error from cluster data placement change ... migration commit in progress for <namespace>

  • Cannot find shardId the chunk belonged to at cluster time ...

Durante a confirmação de uma transação, operações de leitura externa podem tentar ler os mesmos documentos que serão modificados pela transação. Se a transação for gravada em vários shards, durante a tentativa de confirmação nos shards:

  • As leituras externas que usam a read concern "snapshot" ou "linearizable" aguardam até que todas as gravações de uma transação estejam visíveis.

  • As leituras externas que fazem parte de sessões causalmente consistentes (aquelas que incluem afterClusterTime) aguardam até que todas as gravações de uma transação estejam visíveis.

  • As leituras externas que usam outras read concerns não esperam até que todas as gravações de uma transação estejam visíveis, mas leem a versão anterior à transação dos documentos.

Para usar transações em sistemas do MongoDB 4.2 (conjuntos de réplicas e clusters fragmentados), os clientes devem usar drivers do MongoDB atualizados para o MongoDB 4.2.

Em clusters fragmentados com várias instâncias mongos, a execução de transações com drivers atualizados para o MongoDB 4.0 (em vez do MongoDB 4.2) falhará e poderá resultar em erros, incluindo:

Observação

Seu driver pode retornar um erro diferente. Consulte a documentação do seu driver para obter detalhes.

Código de erro
Mensagem de erro
251
cannot continue txnId -1 for session ... with txnId 1
50940
cannot commit with no participants
← API de drivers