Menu Docs

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

Perguntas frequentes: simultaneidade

Nesta página

O MongoDB permite que vários clientes leiam e escrevam os mesmos dados. Para garantir consistência, o MongoDB usa o bloqueio e o controle de concorrência para evitar que os clientes modifiquem os mesmos dados simultaneamente. As gravações em um único documento ocorrem na íntegra ou não ocorrem e os clientes sempre veem dados consistentes.

O MongoDB usa bloqueio multigranular [1] que permite que as operações sejam bloqueadas em nível global, de banco de dados ou de collection e que mecanismos de armazenamento individuais implementem seu próprio controle de concorrência abaixo do nível da collection (por exemplo, no nível do documento no WiredTiger).

O MongoDB usa travas de leitor-gravador que permitem que leitores simultâneos tenham acesso compartilhado a um recurso, como um banco de dados ou uma collection.

Além de um modo de bloqueio compartilhado (S) para leituras e um modo de bloqueio exclusivo (X) para operações de gravação, os modos de intenção compartilhada (IS) e intenção exclusiva (IX) indicam uma intenção de ler ou gravar um recurso usando um bloqueio de granularidade mais fina. Ao bloquear em uma determinada granularidade, todos os níveis superiores são bloqueados usando um bloqueio de intenção.

Por exemplo, ao bloquear uma collection para gravação (usando o modo X), tanto o bloqueio do banco de dados correspondente quanto o bloqueio global devem ser bloqueados no modo de intenção exclusiva (IX). Um único banco de dados pode ser bloqueado simultaneamente nos modos IS e IX, mas um bloqueio exclusivo (X) não pode coexistir com nenhum outro modo, e um bloqueio compartilhado (S) só pode coexistir com bloqueios compartilhados por intenção (IS).

As travas são justas e contêm solicitação de trava para leituras e gravações em fila. No entanto, para otimizar a taxa de transferência, quando uma solicitação de trava é concedida, todas as outras compatíveis são concedidas ao mesmo tempo, potencialmente liberando as travas antes que uma solicitação conflitante seja executada. Por exemplo, considere uma situação em que uma trava X acabou de ser liberada e a fila de conflitos contém estas travas:

IS → IS → X → X → S → IS

Na ordem estrita primeiro a entrar, primeiro a sair (FIFO), apenas os dois primeiros modos IS seriam concedidos. Em vez disso, o MongoDB concederá todos os modos IS e S e, quando todos eles forem drenados, ele concederá X, mesmo que novas solicitações IS ou S tenham sido enfileiradas nesse meio tempo. Como uma concessão sempre moverá todas as outras solicitações para a frente na fila, nenhuma solicitação é possível.

Na saída db.serverStatus() e db.currentOp(), os modos de bloqueio são representados da seguinte forma:

Modo de bloqueio
Descrição
R
Representa bloqueio compartilhado (S).
W
Representa bloqueio exclusivo (X).
r
Representa bloqueio de Intent Shared (IS).
w
Representa bloqueio Intent Exclusive (IX).
[1] Consulte a página da Wikipedia sobre Bloqueio de granularidade múltipla para mais informações.

Para a maioria das operações de leitura e escrita, o WiredTiger usa controle de concorrência otimista. WiredTiger usa apenas bloqueios de intenção nos níveis de banco de dados e coleção. Quando o mecanismo de armazenamento detecta conflitos entre duas operações, uma incorrerá em um conflito de gravação fazendo com que o MongoDB repita essa operação de forma transparente.

Algumas operações globais, normalmente operações de curta duração envolvendo vários bancos de dados, ainda exigem uma trava global de "instância". Outras operações, como collMod, ainda exigem uma trava de banco de dados exclusiva.

Para gerar relatórios sobre informações de utilização de bloqueios, use qualquer um destes métodos:

Especificamente, o documento locks na saída de serverStatus ou o campo locks no current operation reporting fornece informações sobre os tipos de trava e a quantidade de contenções de trava em sua instânciamongod.

Na saída db.serverStatus() e db.currentOp(), os modos de bloqueio são representados da seguinte forma:

Modo de bloqueio
Descrição
R
Representa bloqueio compartilhado (S).
W
Representa bloqueio exclusivo (X).
r
Representa bloqueio de Intent Shared (IS).
w
Representa bloqueio Intent Exclusive (IX).

Para encerrar uma operação, utilize db.killOp().

Em algumas situações, operações de leitura e gravação podem gerar suas travas.

Operações de leitura e gravação de longa duração, como queries, atualizações e exclusões, geram bloqueios sob várias condições. As operações do MongoDB também podem gerar bloqueios entre modificações individuais de documentos em operações de gravação que afetam vários documentos.

Para mecanismos de armazenamento que oferecem suporte ao controle de concorrência no nível de documento, como o WiredTiger, a produção não é necessária ao acessar o armazenamento, pois os bloqueios de intenção, mantidos em nível global, de banco de dados e de collection, não bloqueiam outros leitores e gravadores. No entanto, as operações gerarão periodicamente para:

  • evitar transações de armazenamento de longa duração, pois elas podem exigir a retenção de uma grande quantidade de dados na memória;

  • servir como ponto de interrupção para que você possa encerrar operações de longa duração;

  • permitir operações que exigem acesso exclusivo a uma collection, como descartar e criar índices/collections.

A tabela a seguir lista algumas operações e os tipos de bloqueios que elas usam para mecanismos de armazenamento de bloqueio em nível de documento:

Operação
Banco de dados
collection
Emitir uma query
r (Intenção compartilhada)
r (Intenção compartilhada)
Inserir dados
w (Intenção exclusiva)
w (Intenção exclusiva)
Remover dados
w (Intenção exclusiva)
w (Intenção exclusiva)
Atualizar dados
w (Intenção exclusiva)
w (Intenção exclusiva)
Fazer aggregation
r (Intenção compartilhada)
r (Intenção compartilhada)
Criar um índice (primeiro plano)
W (Exclusiva)
Criar um índice (background)
w (Intenção exclusiva)
w (Intenção exclusiva)
Listar collections

r (Intenção compartilhada)

Alterado na versão 4.0.

Mapear-Reduzir
W (Exclusivo) e R (Compartilhado)
w (Intenção exclusiva) e r (Intenção compartilhada)

Alguns comandos administrativos podem bloquear exclusivamente um banco de dados por longos períodos de tempo. Para sistemas de banco de dados grandes, você pode considerar colocar a instância mongod offline para que os clientes não sejam afetados. Por exemplo, se um mongod fizer parte de um conjunto de réplicas, coloque o mongod offline e deixe que outros nós do conjunto de réplicas processem as solicitações enquanto a manutenção é realizada.

Essas operações administrativas exigem um bloqueio exclusivo no nível do banco de dados por períodos prolongados:

Além disso, o comando renameCollection e o método de shell db.collection.renameCollection() correspondente usam as seguintes travas dependendo da versão do MongoDB:

Comando
MongoDB 4.2.2 ou posterior
MongoDB 4.2.0 - 4.2.1
MongoDB 4.0.X e anterior
renameCollection Comando de banco de dados

Ao renomear uma collection dentro do mesmo banco de dados, o comando renameCollection usará uma trava exclusiva (W) nas collections de origem e destino.

Se o namespace de destino estiver em um banco de dados diferente da collection de origem, o comando renameCollection usará um bloqueio exclusivo (W) no banco de dados de destino ao renomear uma collection entre bancos de dados e bloqueará outras operações nesse banco de dados até que ela seja concluída.

Ao renomear uma collection dentro do mesmo banco de dados, o comando renameCollection usará uma trava exclusiva (W) nas collections de origem e destino.

Se o namespace de destino estiver em um banco de dados diferente do da collection de origem, o comando renameCollection usará uma trava global exclusiva (W) ao renomear uma collection entre bancos de dados e bloqueará outras operações até que seja concluído.

Antes do MongoDB 4.2, o comando renameCollection utilizava um bloqueio exclusivo (W) no banco de dados ao renomear dentro do mesmo banco de dados.
renameCollection() método ajudante de shell
Ao renomear uma collection no mesmo banco de dados, o método renameCollection() usará uma trava exclusiva (W) nas collections de origem e destino.
(mesmo comportamento do MongoDB 4.2.2 ou posterior)
Antes do MongoDB 4.2, o método renameCollection() utilizava um bloqueio exclusivo (W) no banco de dados ao renomear dentro do mesmo banco de dados.

Essas operações administrativas bloqueiam um banco de dados, mas apenas mantêm o bloqueio por um curto período de tempo:

Alterado na versão 4,2.

Essas operações administrativas exigem uma trava exclusiva no nível da collection:

  • Comando create e métodos de shell db.createCollection() e db.createView() correspondentes

  • Comando createIndexes e métodos de shell db.collection.createIndex() e db.collection.createIndexes() correspondentes

  • Comando drop e métodos shell db.collection.drop() correspondentes

  • Comando dropIndexes e métodos de shell db.collection.dropIndex() e db.collection.dropIndexes() correspondentes

  • o comando renameCollection e o método de shell db.collection.renameCollection() correspondente usarão as seguintes travas dependendo da versão:

    • Para renameCollection e db.collection.renameCollection(): para renomear uma collection dentro do mesmo banco de dados, a operação usará uma trava exclusiva (W) nas collections de origem e destino. Versões anteriores ao MongoDB 4.2: a operação usa uma trava exclusiva (W) no banco de dados ao renomear dentro do mesmo banco de dados.

    • Para renameCollection apenas: se o namespace de destino estiver em um banco de dados diferente do da collection de origem, o comportamento de bloqueio dependerá da versão:

      • MongoDB 4.2.2 e posterior A operação usa uma trava exclusiva (W) no banco de dados de destino ao renomear uma collection entre bancos de dados e bloqueia outras operações nesse banco de dados até que ele seja concluído.

      • MongoDB 4.2.1 e versões anteriores A operação usa um bloqueio global exclusivo (W) ao renomear uma collection em bancos de dados e bloqueia outras operações até que seja concluída.

  • o comando reIndex e o método de shell db.collection.reIndex() correspondente usarão as seguintes travas dependendo da versão:

    • No MongoDB 4.2.2 e posterior, essas operações obtêm um bloqueio exclusivo (W) na collection e bloqueiam outras operações na collection até que sejam concluídas.

    • Para o MongoDB 4.0.0 a 4.2.1, essas operações usam um bloqueio global exclusivo (W) e bloqueiam outras operações até a conclusão.

  • o comando replSetResizeOplog utiliza os seguintes bloqueios, dependendo da versão:

    • Na versão 4.2.2 e posterior, essa operação usa uma trava exclusiva (W) na collection oplog e bloqueia outras operações na collection até que ela seja concluída.

    • Para o MongoDB 4.2.1 e versões anteriores, essa operação usa um bloqueio exclusivo global (W) e bloqueia outras operações até que seja concluída.

Antes do MongoDB 4.2, essas operações tinham uma trava exclusiva no banco de dados, bloqueando todas as operações no banco de dados e suas collections até que a operação fosse concluída.

Essas operações do MongoDB podem obter e manter um bloqueio em mais de um banco de dados:

Operação
Comportamento

Alterado na versão 4,2.

Para o MongoDB 4.0.0 a 4.2.1, essas operações usam um bloqueio global exclusivo (W) e bloqueiam outras operações até a conclusão.

A partir da versão 4.2.2, essas operações obtêm apenas uma trava de collection exclusiva (W) em vez de uma trava global exclusiva.

Antes do MongoDB 4.0, essas operações obtinham uma trava de banco de dados exclusiva (W).

Alterado na versão 4,2.

Na versão 4.2.1 e anteriores, essa operação obtém uma trava global exclusiva (W) ao renomear uma collection entre bancos de dados e bloqueia outras operações até que sejam concluídas.

A partir do MongoDB 4.2.2, essa operação obtém apenas uma trava exclusiva (W) no banco de dados de destino, uma trava de intenção compartilhada (r) no banco de dados de origem e uma trava compartilhada (S) na collection de origem em vez de uma trava global exclusiva.

Alterado na versão 4,2.

Para o MongoDB 4.2.1 e versões anteriores, essa operação obtém um bloqueio global exclusivo (W) e bloqueia outras operações até a conclusão.

A partir do MongoDB 4.2.2, essa operação obtém apenas um bloqueio exclusivo (W) na collection oplog em vez de um bloqueio exclusivo global.

A fragmentação melhora a simultaneidade ao distribuir collections em diversas instâncias mongod, permitindo que servidores de shards (especificamente, processos mongos) sejam executados simultaneamente com as instâncias mongod downstream.

Em um cluster fragmentado, as travas se aplicam a cada shard individual, não a todo o cluster; ou seja, cada instância mongod é independente das outras no cluster fragmentado e usa suas próprias travas. As operações em uma instância mongod não bloqueiam as operações em nenhuma outra.

Com conjuntos de réplicas, quando o MongoDB grava em uma collection no primary, também grava no oplog do primary, que é uma collection especial no banco de dados local. Portanto, o MongoDB deve bloquear o banco de dados da collection e o banco de dados local. O mongod deve bloquear ambos os bancos de dados ao mesmo tempo para mantê-los consistentes e garantir que as operações de gravação, mesmo com replicação, sejam tudo ou nada.

Ao gravar em um conjunto de réplicas, o escopo da trava se aplica ao primary.

Na replicação, o MongoDB não aplica gravações em série a secundários. Os secundários coletam entradas de oplog em lotes e depois aplicam esses lotes em paralelo. As gravações são aplicadas na ordem em que aparecem no oplog.

A partir do MongoDB 4.0, lê quais secundários de destino leem de um snapshot WiredTiger dos dados se o secundário estiver passando por replicação. Isso permite que a leitura ocorra simultaneamente com a replicação, ao mesmo tempo em que garante uma visualização consistente dos dados. Antes do MongoDB 4.0, as operações de leitura em secundários eram bloqueadas até que qualquer replicação em andamento fosse concluída. Consulte Replicação multithreaded para obter mais informações.

Porque um único documento pode conter dados relacionados que, de outra forma ser modelado em tabelas pai-filho separadas em um esquema relacional, as operações atômicas de documento único do MongoDB já fornecem semântica de transações que atende às necessidades de integridade de dados da maioria dos aplicativos. Um ou mais campos podem ser escritos em uma única operação, incluindo em vários subdocumentos e elementos de uma array. As garantias fornecidas pelo MongoDB garantem o isolamento completo como o documento é atualizado; qualquer erro faz com que a operação seja revertida eque os clientes recebam uma visão consistente do documento.

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.

Para obter mais informações, consulte transações.

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.

Dependendo da read concern, os clientes podem ver os resultados das gravações antes que elas sejam duráveis. Para controlar se a leitura dos dados pode ser revertida ou não, os clientes podem usar a opção readConcern.

Novidades na versão 5,0.

Uma operação de leitura sem bloqueio é executada imediatamente: ela não é bloqueada quando outra operação tem um bloqueio de gravação exclusivo (X) na collection.

A partir do MongoDB 5.0, as seguintes operações de leitura não são bloqueadas quando outra operação mantém um bloqueio de escrita exclusivo (X) na collection:

Ao escrever em uma collection, mapReduce e aggregate mantêm uma trava exclusiva de intenção (IX). Portanto, se uma trava X exclusiva já estiver mantida em uma collection, as operações de escrita mapReduce e aggregate serão bloqueadas.

Para obter mais informações, consulte:

← FAQ: Índices