BT

Disseminando conhecimento e inovação em desenvolvimento de software corporativo.

Contribuir

Tópicos

Escolha a região

Início Notícias Jepsen contesta alegações de consistência de dados do MongoDB

Jepsen contesta alegações de consistência de dados do MongoDB

Em um artigo intitulado MongoDB and Jepsen, a empresa MongoDB afirmou que o banco de dados passou "nos testes de segurança, correção e consistência de dados mais difíceis do setor". Em resposta, Jepsen publicou um artigo declarando que o MongoDB 3.6.4 havia falhado em alguns de seus testes, porém, o MongoDB 4.2.6 teve ainda mais problemas, incluindo "transações retro-causais", nas quais uma transação reverte a ordem para que uma leitura possa ver o resultado de uma gravação futura.

A resposta da Jepsen LLC começa com esta resposta a Maxime Beugnet no feed do perfil oficial no Twitter:

Tenho que admitir que levantei uma sobrancelha quando vi essa notícia. Nesse relatório, o MongoDB perdeu dados e violou a causalidade (quando a execução das ordens estão fora de ordem) por padrão. De alguma forma, isso se tornou "uma das mais fortes garantias de consistência, correção e segurança de dados de qualquer banco de dados disponível hoje"!

O relatório em questão foi intitulado MongoDB 3.6.4 por Kit Patella. O novo relatório, de Kyle Kingsbury, descreve mais sobre o assunto:

Da mesma forma, o nível padrão para a operação de leitura no MongoDB preocupa, pois permite leituras abortadas: os leitores podem observar um estado no qual o commit ainda não foi finalizado e que pode ser descartado no futuro. Como é possível observar na documentação da consistência de isolamento de leitura, "Ler dados não persistidos é o nível de isolamento padrão".

Descobrimos que, devido a esse padrão fraco, as sessões do MongoDB não preservavam a consistência causal por padrão: os usuários precisam especificar as configurações de "read concern" e "write concern" como "majority" (ou qualquer opção mais restritiva) para obter a consistência causal. O MongoDB fechou o problema, dizendo que estava funcionando como projetado, e atualizou sua documentação de isolamento salientando que, embora o MongoDB ofereça "consistência causal nas sessões do cliente", essa garantia não será válida, a menos que o usuário tome cuidado ao usar os isolamentos corretos de leitura e gravação. Uma tabela detalhada mostra as propriedades oferecidas com as configurações com opções menos restritivas de leitura e gravação.

Falhas no isolamento da transação

Nos últimos anos, o MongoDB vem divulgando fortemente os recursos transacionais. Mas, Jepsen descobriu que o suporte transacional não funciona por padrão. Em um de seus testes, as transações foram usadas para acrescentar valores a um documento. Eles descobriram que, mesmo com as configurações de "write concern" sendo "majority" no nível do banco de dados/coleção, "as transações pareciam perder gravações reconhecidas" ao usar o isolamento de gravação padrão no nível transacional. Isso pode ser resolvido especificando explicitamente o isolamento do "write concern" no nível da transação.

Os clientes observaram uma lista contínua e crescente de elementos até [1 2 3 4 5 6 7], momento em que a lista foi redefinida para [] e começou novamente com [8]. Este exemplo de rollback do MongoDB é uma maneira elegante de dizer "perda de dados".

Isso é ruim, mas surge uma pergunta ainda mais sutil: por que fomos capazes de ler esses valores? Afinal, o isolamento do "read concern" no "linearizable" deve mostrar apenas escritas de nível "majority" reconhecidas, ou seja, permanentes. A resposta é surpreendente, mas documentada, escolha de design do MongoDB:

As operações em uma transação possuem níveis transacionais de "read concern". Ou seja, qualquer "read concern" definido no nível de coleção e no banco de dados é ignorado dentro da transação.

Efetivamente, isso significa "transações sem uma 'read concern' explícita, rebaixam o nível de restrição no banco de dados ou na coleção, ao que está sendo utilizado como padrão no nível local", permitindo que a transação leia dados não enviados que podem ser revertidos posteriormente.

O inverso também é problemático. De acordo com a documentação, "Se a transação não usar o 'write concern' no nível 'majority' para o envio, o isolamento do 'read concern' no 'snapshot' não oferece garantia de que as operações de leitura que usam o nível 'snapshot' leiam apenas os dados enviados com o nível 'majority'". Em outras palavras, o modo "snapshot" do "read concern" é efetivamente ignorado se não definir o isolamento do "write concern". E, novamente, isso deve ser feito no nível da transação, porque elas ignoram as configurações da coleção e do banco de dados.

Transações retro-causais

Mesmo com o isolamento no "snapshot", havia vários cenários com resultados inesperados. Muitos deles são complexos demais para resumir aqui, mas um deles realmente se destacou.

Em um teste, os pesquisadores da Jepsen disseram ao cliente para ler um documento e acrescentar um valor a ele. No início do teste, o documento continha a sequência [2, 3, 4]. Após a leitura do valor, o documento foi alterado para [1, 2, 3, 4].

Isso geralmente funcionava, mas em quatro transações o cliente leu [1, 2, 3, 4] no banco de dados. Kingsbury continua:

Naturalmente, isso é impossível: O teste envia as operações de cada transação em ordem restrita e, a menos que o MongoDB construa uma máquina do tempo, ele não pode retornar valores que ainda não sabem que serão gravados. Isso sugere que a transação retro-causal foi executada duas vezes e, na segunda execução, observou um efeito de sua própria execução anterior. Isso pode ser outra consequência de um mecanismo inadequado de nova tentativa.

Esta não é a única vez que o mecanismo de nova tentativa foi responsabilizado.

Descobrimos que as partições de rede podem fazer com que o MongoDB duplique os efeitos das transações. Apesar de nunca anexar o mesmo valor a uma matriz duas vezes, observamos matrizes com várias cópias do mesmo elemento, repetidamente.

Na tentativa de entender melhor esses comportamentos, os pesquisadores tentaram desativar as tentativas automáticas apenas para descobrir que "as transações do MongoDB ignoram a configuração retryWrites e continuam tentando, independentemente da configuração".

Além de oferecer conselhos aos desenvolvedores sobre como usar o MongoDB com mais segurança, a Jepsen recomenda que "o MongoDB revise sua linguagem de marketing para usar 'snapshot isolated' ao invés de 'ACID'".

Nota dos editores: Uma versão anterior deste artigo mostrava que essa perda de dados sempre poderia ocorrer ao usar as transações. Esse problema específico ocorreu apenas quando usamos o "write concern" padrão nas transações. No entanto, outras anomalias foram detectadas com as transações usando o isolamento do "write concern" no "majority".

Avalie esse artigo

Relevância
Estilo/Redação

Conteúdo educacional

BT