Write Concern em Replica Sets MongoDB

Write Concern em Replica Sets MongoDB

No artigo Configuração de um Replica Set no MongoDB, eu detalhei o que é e como criar um Replica Set no MongoDB, e neste artigo, vou abordar um conceito fundamental para manter a consistência das escritas entre os membros de um Replica Set: o Write Concern.

O que é o Write Concern?

O Write Concern no MongoDB é uma configuração que controla o nível de confirmação antes do servidor de banco de dados considerar uma operação de escrita bem sucedida. Em outras palavras, ele indica em quantos nós do Replica Set a escrita precisa acontecer antes que a aplicação receba uma confirmação da escrita solicitada.

A configuração do Write Concern é composta por três parâmetros:

{ w: <valor>, j: <boolean>, wtimeout: <ms> }
  • w: Quantos membros devem confirmar a escrita;
  • j: Se a escrita deve ser confirmada no journal;
  • wtimeout: Tempo máximo de espera em milissegundos para retorno da confirmação dos membros.

O parâmetro “w” pode assumir os seguintes valores:

w: 0 -> é o valor que traz mais performance às escritas, pois envia a escrita para o banco de dados e não aguarda confirmação alguma. Isso significa que se por algum motivo o banco de dados não conseguir realizar a escrita, a aplicação que solicitou ela não identificará o problema. Pode ser útil para aplicações onde a perda de um registro não impacta no panorama geral, como em alguns casos de time series ou logs de alta frequência;

w: 1 -> a escrita aguarda a confirmação apenas do nó primário. Nesse caso, existe uma confirmação da escrita, porém o dado pode não ter sido replicado para os secundários do Replica Set. Aqui entra o cenário de consistência eventual: todos os nós do Replica Set eventualmente terão esse dado, porém não ao mesmo tempo. Ou seja, o membro secundário pode levar algum tempo até receber esse dado, e se um segundo client realizar uma leitura no secundário desatualizado, ele não terá uma visão atualizada dos dados (a depender do Read Concern configurado). Além disso, caso uma eleição ocorra, e um secundário que não recebeu o dado seja eleito como primário, o dado não replicado será eliminado do antigo primário, através de um rollback. Por esse motivo, esse nível de Write Concern pode não ser o mais recomendado para ambientes produtivos com dados críticos;

w: “majority” -> é o modo padrão do MongoDB, onde a escrita precisa ser confirmada na maioria dos membros votantes do Replica Set. A fórmula de cálculo da maioria é: maioria = floor(total_membros_votantes / 2) + 1. Em um Replica Set de três nós, por exemplo, a escrita é considerada bem sucedida quando dois dos três membros confirmarem a escrita (o primário + um secundário). Esse modo adiciona um melhor nível de segurança, adicionando um overhead à performance, uma vez que mais membros precisam confirmar a escrita. Utilizando o Write Concern como “majority” e configurando o Read Concern como “majority” (a leitura só retorna dados que foram confirmados pela maioria dos nós do Replica Set) eliminamos o cenário de consistência eventual.

w: <número> -> especifica um número específico de membros do Replica Set que devem confirmar a escrita. Por exemplo, para um Replica Set de três nós, onde se deseja que todos os membros retornem a confirmação antes de considerar a escrita bem sucedida, o parâmetro w:3 pode ser usado.

Já o parâmetro “j”, controla se a escrita deve ser confirmada no journal, e pode ser configurado com true ou false. O journal no MongoDB é onde o log de operações é escrito, antes das escritas serem efetuadas nos arquivos de dados (similar ao WAL do PostgreSQL ou o redo do Oracle). Isso evita que em um cenário de queda da instância do MongoDB, as escritas não aplicadas aos arquivos de dados sejam recuperadas do journal no próximo restart da instância. Para o MongoDB das versões 7.0 ou superior, o journal é habilitado por padrão. Para versões anteriores o parâmetro de servidor journal controla o comportamento padrão.

Por fim, o parâmetro “wtimeout” define por quantos milissegundos o MongoDB aguarda pela confirmação de escrita do Write Concern configurado. Caso não seja retornado dentro do timeout, o MongoDB levanta um WriteConcernError, alertando que o número de confirmações de escrita não foi alcançado. Algo importante aqui: o Mongo não desfaz as escritas dos nós que confirmaram a escrita, mesmo que esse timeout seja excedido. Caso seja necessário desfazer essa alteração, é a aplicação que precisa implementar uma tratativa de erro específica. Outro cenário: mesmo que esse erro ocorra, o dado pode ser eventualmente replicado para os membros que não retornaram um reconhecimento de escrita. Isso pode ocorrer em um cenário onde um dos hosts está com uma carga alta, e está com um lag elevado de replicação.

Como configurar?

O Write Concern pode ser configurado em diversos níveis:

Nível de operação: especifica o Write Concern no comando de inserção:

db.my_collection.insertOne(
  { msg: "teste majority" },
  { writeConcern: { w: "majority", wtimeout: 3000 } }
)

Nível de sessão: para configurar um nível específico para a sessão, a string de conexão pode ser parametrizada de acordo com Write Concern desejado:

mongodb://mongo01:27017,mongo02:27017,mongo03:27017/?replicaSet=rsMyReplicaSet&w=majority&wtimeoutMS=5000

Nível de servidor: controla o Write Concern padrão do servidor. O Write Concern pode ser verificado no campo defaultWriteConcern do retorno do comando db.adminCommand({ getDefaultRWConcern: 1 }):

rsIndexaLearn [direct: primary] admin> db.adminCommand({ getDefaultRWConcern: 1 })
{
  defaultReadConcern: { level: 'local' },
  defaultWriteConcern: { w: 'majority', wtimeout: 3000 },
  updateOpTime: Timestamp({ t: 1776347993, i: 1 }),
  updateWallClockTime: ISODate('2026-04-16T13:59:59.437Z'),
  defaultWriteConcernSource: 'global',
  defaultReadConcernSource: 'implicit',
  localUpdateWallClockTime: ISODate('2026-05-01T18:57:25.771Z'),
  ok: 1,
  '$clusterTime': {
    clusterTime: Timestamp({ t: 1777662648, i: 1 }),
    signature: {
      hash: Binary.createFromBase64('iW99gnLTgEnJzvVj1bBltojJaLY=', 0),
      keyId: Long('7612427390077108230')
    }
  },
  operationTime: Timestamp({ t: 1777662648, i: 1 })
}

Para alterar o Write Concern padrão, utiliza-se o comando setDefaultRWConcern:

db.runCommand({
  setDefaultRWConcern: 1,
  defaultWriteConcern: { w: 1, j: true }
})

Impactos de performance

Para demonstrar o impacto do Write Concern na performance das escritas, vou criar uma função que mensure o tempo da escrita de 1000 documentos em uma collection chamada benchmark:

function medirTempo(label, writeConcern) {
  const inicio = new Date()
  for (let i = 0; i < 1000; i++) {
    db.benchmark.insertOne({ i }, { writeConcern })
  }
  const fim = new Date()
  print(label, "->", fim - inicio, "ms")
}

Agora, executamos ela, repassando diferentes níveis de Write Concern:

rsIndexaLearn [direct: primary] admin> medirTempo("w:0          ", { w: 0 })
w:0           -> 669 ms

rsIndexaLearn [direct: primary] admin> medirTempo("w:1          ", { w: 1 })
w:1           -> 1603 ms

rsIndexaLearn [direct: primary] admin> medirTempo("w:majority   ", { w: "majority" })
w:majority    -> 18274 ms

No meu caso, esse benchmark foi executado em um ambiente de testes, onde o Replica Set contém três membros, ou seja, o “majority” precisa confirmar a escrita no primário e um secundário. Como o esperado, podemos notar que conforme a consistência da escrita aumenta, as operações ficam mais lentas, devido ao aumento do número de confirmações necessárias. Aqui temos mais um exemplo do trade-off entre segurança e performance da área de tecnologia.

Conclusão

Simplesmente ter um Replica Set não é a garantia que seus dados estão a salvo no MongoDB. Também é necessário configurar corretamente o Write Concern e o Read Concern (que abordarei em um post futuro) para que tenhamos um nível de consistência maior.

Caso você deseja aprofundar seu conhecimento, temos encontros mensais gratuitos abordando diversos temas do MongoDB na IndexaLearn. Você pode se cadastrar gratuitamente nesses eventos clicando aqui.

Deixe um comentário

O seu endereço de e-mail não será publicado. Campos obrigatórios são marcados com *