Base de consulta de incidentes reais de MongoDB. Cada artigo traz o resumo do caso, o checklist de
diagnóstico e resolução, os comandos usados com exemplos e os links da documentação oficial. Novos
casos entram como novos artigos ao final.
createIndexes pendurado no currentOp por mais de 90 minutos
Nó hidden com votes: 1 fora do ar + commit quorum padrão (votingMembers)
killOp e recriação dos índices com commitQuorum "majority"
Antes de copiar um comandoBanco, coleção, índices e hosts dos exemplos são fictícios: troque pelos do seu ambiente. Os links apontam para mongodb.com/docs/manual na versão mais recente; use o seletor de versão da página para a versão do seu servidor.
Index build travado (createIndexes pendurado)
Dois createIndexes ficaram pendurados por mais de 90 minutos em uma coleção pequena, porque um nó hidden votante estava fora do ar e o commit quorum padrão exige todos os votantes.
index buildcommit quorumreplica sethidden
Resumo do incidente e lições
Incidente em uma coleção pequena de um replica set de 5 membros votantes, 2 deles hidden. Dois createIndexes iniciados pelo MongoDB Compass ficaram pendurados no currentOp por mais de 90 minutos, apesar de a coleção ter só centenas de documentos.
Item
Detalhe
Sintoma
Dois createIndexes (via MongoDB Compass) apareciam no currentOp por mais de 90 minutos.
Coleção
nome-base-dados.nome-collection (341 documentos, ~135 KB). Coleção pequena: lentidão não era a causa.
Replica set
rsExemplo, 5 membros votantes, 2 deles hidden (nós 4 e 5, com votes: 1).
Causa
O nó mongodb-app-4 (hidden, votes: 1) estava fora do ar. O commit quorum padrão (votingMembers) exige todos os votantes com dados, então o build não finalizava.
Resolução
Os builds foram abortados com killOp e os índices recriados com commitQuorum: "majority".
Pendências
Recuperar o nó 4 e decidir sobre votes: 0 nos hidden.
Lições do incidente
Hidden não é "fora do voto"Membro hidden com votes: 1 conta no commit quorum padrão do index build. A queda dele trava o createIndex com quorum padrão.
getIndexes() pode listar índices em construçãoVer o índice na lista não prova que o build terminou. Verifique também o currentOp.
killOp descarta o índiceEm um createIndexes pendente, o killOp aborta o build e o índice é removido. Não assuma que ele sobrevive.
setIndexCommitQuorum atua em um build por vezCada createIndexes com um índice é um build separado. Passar nomes de builds diferentes na mesma chamada retorna IndexNotFound ("Cannot find an index build... with the provided index names"), mesmo com os builds ativos. Chame o comando uma vez por índice (veja o passo "Criar, ajustar e remover índices").
Collection: { W: 1 } em lockStats é históricoÉ uma contagem acumulada, não um lock ativo. Para saber se há bloqueio, olhe locks e waitingForLock.
Colagem no mongoshBlocos multilinha colados com o prompt de continuação (|) geram SyntaxError. Cole em uma linha só.
Conceitos: commit quorum, hidden e maioria
Os conceitos que explicam por que um index build pode ficar parado esperando um nó que nem recebe leituras.
Conceito
Resumo
Documentação
Commit quorum
Quantos membros devem concluir o build antes do commit. O padrão é votingMembers (todos os votantes com dados).
ConfirmarcurrentOp vazio e getIndexes() no primário e nos secundários (veja o passo de secundários).
Resolver a causa raiz
Recuperar o nó que está fora ou avaliar votes: 0 nos hidden.
PrevençãoEm ferramentas gráficas como o Compass, o commit quorum é o padrão. Enquanto houver um votante fora, crie índices pelo shell com "majority".
Monitorar operações e index builds
db.currentOp()
Lista as operações em andamento no servidor e aceita um documento de filtro. Campos úteis: opid (usado no killOp), secs_running, ns, command, msg/progress (fase e progresso do index build), locks/waitingForLock e client/appName (origem, ex.: MongoDB Compass).
mongosh
db.currentOp({ "command.createIndexes": { $exists: true } })
// Filtrar pelo namespace
db.currentOp({ ns: "nome-base-dados.nome-collection" })
// Namespace ou fase de index build
db.currentOp({ $or: [ { ns: "nome-base-dados.nome-collection" }, { msg: /Index Build/ } ] })
Campo
Significado
opid
Identificador da operação (usado no killOp).
secs_running
Há quantos segundos a operação roda.
ns
Namespace (banco.coleção).
command
Comando em execução (ex.: createIndexes e os índices).
msg / progress
Fase e progresso (done/total) de operações como index build.
Equivalente em aggregation do currentOp, mais flexível para filtrar e projetar. Deve ser executado no banco admin. Opções comuns: allUsers (operações de todos os usuários), idleConnections e idleSessions.
Retorna sessões com transação aberta. Uma transação longa pode bloquear o commit final de um index build. No incidente a consulta não retornou nada, o que descartou essa hipótese.
Retorna estatísticas de armazenamento: count, size, storageSize, totalIndexSize, indexSizes e nindexes. Foi usado para constatar que a coleção era pequena (341 documentos), descartando lentidão como causa. Em versões recentes, a alternativa é o estágio $collStats.
Em secundários é preciso permitir leitura, com setReadPref("secondaryPreferred") ou rs.secondaryOk() (conforme a versão do mongosh). Repita em cada membro.
Altera o commit quorum de um index build em andamento, sem abortá-lo. O indexNames deve corresponder exatamente a um único build. Se os índices foram criados em comandos createIndexes separados, execute uma chamada por índice. Era a alternativa que preservaria os índices, em vez do killOp. Retorna IndexNotFound quando os nomes não correspondem a um build ativo.
O terceiro argumento é o commitQuorum. Com "majority", o build finaliza quando a maioria dos votantes com dados confirma, e a queda de um nó não trava a operação.
Estado em tempo real do replica set: papel de cada membro (PRIMARY, SECONDARY), health, optime, lastHeartbeatMessage (mostrou "Connection refused" no nó 4) e writeMajorityCount.
mongosh
rs.status()
// Versão resumida usada no incidente
rs.status().members.map(m => ({ name: m.name, state: m.stateStr, health: m.health, lag: m.optimeDate }))
Aplica uma nova configuração. Zerar votes exige priority: 0 (já é o caso dos hidden). Os nós continuam replicando, mas deixam de contar para eleições, maioria de escrita e commit quorum de index build.