O que o MongoDB não era compatível com ACID antes da v4 realmente significava?


226

Não sou especialista em banco de dados e não tenho formação formal em ciência da computação, então tenha paciência comigo. Quero conhecer os tipos de coisas negativas do mundo real que podem acontecer se você usar uma versão antiga do MongoDB anterior à v4 , que não era compatível com ACID . Isso se aplica a qualquer banco de dados não compatível com ACID.

Eu entendo que o MongoDB pode executar Operações Atômicas , mas que eles "não suportam o bloqueio tradicional e transações complexas", principalmente por razões de desempenho. Também entendo a importância das transações do banco de dados, e o exemplo de quando o banco de dados é para um banco, e você está atualizando vários registros que precisam estar sincronizados. Você deseja que a transação volte ao estado inicial, se houver um falta de energia elétrica para que o crédito seja igual à compra etc.

Mas quando converso sobre o MongoDB, aqueles que não conhecem os detalhes técnicos de como os bancos de dados são realmente implementados começam a usar declarações como:

O MongoDB é muito mais rápido que o MySQL e o Postgres, mas há uma pequena chance, como 1 em um milhão, de que "não seja salvo corretamente".

Essa parte "não salva corretamente" está se referindo a este entendimento: se houver uma queda de energia no momento em que você estiver gravando no MongoDB, há uma chance de um registro específico (digamos que você esteja acompanhando visualizações de página em documentos com 10 atributos cada), que um dos documentos salvou apenas cinco dos atributos ... o que significa que, com o tempo, seus contadores de visualizações de página ficarão "ligeiramente" desligados. Você nunca saberá quanto, você saberá que eles estarão 99,999% corretos, mas não 100%. Isso ocorre porque, a menos que você tenha feito especificamente dessa operação atômica o mongodb , não é garantido que a operação seja atômica.

Portanto, minha pergunta é: qual é a interpretação correta de quando e por que o MongoDB pode não "salvar corretamente"? Que partes do ACID ele não atende e em que circunstâncias, e como você sabe quando esses 0,001% dos seus dados estão desativados? Isso não pode ser corrigido de alguma forma? Caso contrário, isso parece significar que você não deve armazenar coisas como sua userstabela no MongoDB, porque um registro pode não ser salvo. Mas, novamente, esse 1 / 1.000.000 de usuário pode precisar "tentar se inscrever novamente", não?

Estou apenas procurando talvez uma lista de quando / por que coisas negativas acontecem com um banco de dados não compatível com ACID como o MongoDB e, idealmente, se houver uma solução padrão (como executar um trabalho em segundo plano para limpar dados ou usar SQL apenas para isso, etc.) .

Respostas:


133

Uma coisa que você perde com o MongoDB são as transações com várias coleções (tabela). Modificadores atômicos no MongoDB podem funcionar apenas em um único documento.

Se você precisar remover um item do inventário e adicioná-lo ao pedido de alguém ao mesmo tempo - não poderá. A menos que essas duas coisas - estoque e pedidos - existam no mesmo documento (o que provavelmente não existe).

Encontrei esse mesmo problema em um aplicativo em que estou trabalhando e tinha duas soluções possíveis para escolher:

1) Estruture seus documentos da melhor maneira possível e use modificadores atômicos da melhor maneira possível e, para o bit restante, use um processo em segundo plano para limpar registros que podem estar fora de sincronia. Por exemplo, removo itens do inventário e os adiciono a uma matriz reservadaInventory do mesmo documento usando modificadores atômicos.

Isso sempre me informa que os itens NÃO estão disponíveis no inventário (porque são reservados por um cliente). Quando o cliente faz check-out, removo os itens do ReservedInventory. Não é uma transação padrão e, como o cliente pode abandonar o carrinho, preciso de algum processo em segundo plano para encontrar e encontrar carrinhos abandonados e mover o inventário reservado de volta ao pool de inventário disponível.

Obviamente, isso é menos do que o ideal, mas é a única parte de uma grande aplicação em que o mongodb não se encaixa perfeitamente na necessidade. Além disso, ele funciona perfeitamente até agora. Isso pode não ser possível para muitos cenários, mas, devido à estrutura do documento que estou usando, ele se encaixa bem.

2) Use um banco de dados transacional em conjunto com o MongoDB. É comum usar o MySQL para fornecer transações para as coisas absolutamente necessárias, enquanto o MongoDB (ou qualquer outro NoSQL) faz o que é melhor.

Se minha solução do nº 1 não funcionar a longo prazo, investigarei mais sobre a combinação do MongoDB com o MySQL, mas, por enquanto, o nº 1 atende bem às minhas necessidades.


27
" Modificadores atômicos no MongoDB só podem funcionar em uma única coleção " => Eu acho que você quis dizer "em um único documento ".
Assilias

2
Excelente informação, geralmente uma excelente resposta, com exceção de sugerir o uso do MySQL.
Doug Molineux 23/10

״ Uma coisa que você perde com o MongoDB são as transações com várias coleções (tabela). Modificadores atômicos no MongoDB podem funcionar apenas com um único documento ״ do mongo doc ( docs.mongodb.com/v3.2/core/write-operations-atomicity ): "No MongoDB, uma operação de gravação é atômica no nível de um único documento, mesmo que a operação modifique vários documentos incorporados em um único documento ".
yoav.str

5
A falta de transações ACID para vários documentos não é mais o caso. O MongoDB anunciou que está chegando na v4.0. Veja mongodb.com/blog/post/multi-document-transactions-in-mongodb
Grigori Melnik

1
Por enquanto, como o MongoDB 4.0 é compatível com ACID, mongodb.com/transactions com transações com vários documentos. Dê uma olhada em mongodb.com/blog/post/…
Ratah

134

Na verdade, não é correto que o MongoDB não seja compatível com ACID. Pelo contrário, o MongoDB é compilador de ACID no nível do documento .

Qualquer atualização em um único documento é

  • Atômico: ele é totalmente concluído ou não
  • Consistente: nenhum leitor verá uma atualização "parcialmente aplicada"
  • Isolado: novamente, nenhum leitor verá uma leitura "suja"
  • Durável: (com a preocupação de gravação apropriada)

O que o MongoDB não possui são transações - ou seja, atualizações de vários documentos que podem ser revertidas e compatíveis com ACID.

Observe que você pode criar transações sobre as atualizações compatíveis com ACID em um único documento usando a confirmação em duas fases .


3
Observe que as transações de confirmações de duas fases não são compatíveis com ACID. Por alguma razão, deduzi o oposto até seguir o link.
Justin C

1
Há alguma dúvida sobre a durabilidade do MongoDB distribuído no nível do documento, independentemente da configuração da preocupação com gravação. A ferramenta de código aberto Jepsen descobriu que os dados podem ser perdidos em face de uma partição de rede, mesmo com a preocupação de escrever MAJORITY. Veja a escrever-se aqui: aphyr.com/posts/284-call-me-maybe-mongodb
jrullmann

9
Ter ACID no nível de um único documento, que de alguma forma equivalente a um único registro no RDBMS, não é útil em muitos casos. O termo da transação não se refere à tabela única, e você pode até ter um mecanismo de confirmação em duas fases e envolver vários XAResource, portanto, referir-se ao documento único como compatível com ACID é um tanto problemático, IMHO.
Yair Zaslavsky

5
Concorde com Yair. "Compatível com ACID no nível do documento" não é um ponto de venda. Basicamente, significa apenas "não compatível com ACID". O ACID nunca foi concebido para ser "apenas uma linha / documento / entidade". Trata-se de manter seus dados consistentes em todo o banco de dados.
joshua.paling

34

Uma boa explicação está contida em "A Starbucks não usa confirmação bifásica" .

Não se trata de bancos de dados NoSQL, mas ilustra o fato de que às vezes você pode perder uma transação ou ter seu banco de dados temporariamente em um estado inconsistente.

Eu não consideraria algo que precisa ser "consertado". A correção é usar um banco de dados relacional compatível com ACID. Você escolhe uma alternativa NoSQL quando seu comportamento atende aos requisitos de seu aplicativo.


1
Como qualquer analogia, tem suas limitações. No software, é fácil criar novos Array [Cashiers] e fazer com que eles processem transações síncronas cada um, enquanto o custo real seria ridiculamente caro.
HRJ 07/12/12

16

Acho que outras pessoas já deram boas respostas. No entanto, gostaria de acrescentar que existem bancos de dados ACID NOSQL (como http://ravendb.net/ ). Portanto, não é apenas a decisão NOSQL - sem ACID vs Relacional com ACID ....


1
obrigado @subGate. alguém por aí que possa compartilhar sua experiência com o ravenDB e se ele realmente satisfaz o requisito?
Nir Pengas

12

"não será salvo corretamente" pode significar:

  1. Por padrão, o MongoDB não salva suas alterações na unidade imediatamente. Portanto, existe a possibilidade de você dizer ao usuário "a atualização foi bem-sucedida", a falta de energia ocorre e a atualização é perdida. O MongoDB fornece opções para controlar o nível de atualização "durabilidade". Pode esperar que as outras réplicas recebam essa atualização (na memória), aguardar a gravação no arquivo de diário local etc.

  2. Não há atualizações "atômicas" fáceis para várias coleções e até vários documentos na mesma coleção. Na maioria dos casos, não é um problema, pois pode ser contornado com o Confirmação em Duas Fases ou reestruturar seu esquema para que as atualizações sejam feitas em um único documento. Consulte esta pergunta: Bancos de dados de documentos: dados redundantes, referências, etc. (MongoDB especificamente)


10

A partir do MongoDB v4.0, as transações ACID para vários documentos devem ser suportadas. Por meio do isolamento de instantâneos, as transações fornecerão uma visão global consistente dos dados e reforçarão a execução de tudo ou nada para manter a integridade dos dados.

Eles se sentem como transações do mundo relacional, por exemplo:

with client.start_session() as s:
    s.start_transaction()
    try:
        collection.insert_one(doc1, session=s)
        collection.insert_one(doc2, session=s)
        s.commit_transaction()
    except Exception:
        s.abort_transaction()

Consulte https://www.mongodb.com/blog/post/multi-document-transactions-in-mongodb


O primeiro release candidate do MongoDB4.0 está fora - linkedin.com/pulse/mongodb-40-rc0-now-available-grigori-melnik
Grigori Melnik

5

Leia sobre as propriedades do ACID para obter uma melhor compreensão.

Também na documentação do MongoDB, você pode encontrar uma pergunta e resposta .

O MongoDB não é compatível com ACID. Leia abaixo para obter uma discussão sobre a conformidade com o ACID.

  1. O MongoDB é Asóbrio no nível do documento. Ele não está de acordo com a definição de atômica que conhecemos dos sistemas de bancos de dados relacionais, em particular o link acima. Nesse sentido, o MongoDB não está de acordo com o A do ACID.
  2. O MongoDB é Conitente por padrão. No entanto, você pode ler de servidores secundários em um conjunto de réplicas. Você só pode ter consistência eventual neste caso. Isso é útil se você não se importa de ler dados ligeiramente desatualizados.
  3. O MongoDB não garante a Isolação (novamente de acordo com a definição acima):
  1. Para sistemas com vários leitores e gravadores simultâneos, o MongoDB permitirá que os clientes leiam os resultados de uma operação de gravação antes que a operação de gravação retorne.
  2. Se o mongod terminar antes que o diário seja confirmado, mesmo se uma gravação retornar com êxito, as consultas poderão ter dados de leitura que não existirão após a reinicialização do mongod.

No entanto , o MongoDB modifica cada documento isoladamente (para inserções e atualizações); somente no nível do documento, não nas transações com vários documentos.

  1. Em relação à Durabilidade - você pode configurar esse comportamento com a write concernopção, embora não tenha certeza. Talvez alguém saiba melhor.

Eu acredito que algumas pesquisas estão em andamento para mover o NoSQL para restrições ACID ou similares. Esse é um desafio, porque os bancos de dados NoSQL geralmente são rápidos (er) e as restrições do ACID podem diminuir significativamente o desempenho.


4

A única razão pela qual o atomic modifica o trabalho em uma coleção única é porque os desenvolvedores do mongodb trocaram recentemente um bloqueio de banco de dados com um bloqueio de gravação amplo da coleção. Decidir que o aumento da concorrência aqui valeu a pena. Na sua essência, o mongodb é um arquivo mapeado na memória: eles delegaram o gerenciamento de buffer pool ao subsistema vm da máquina. Como está sempre na memória, eles conseguem se livrar de bloqueios granulares muito curtos: você realizará apenas operações na memória enquanto a segura, o que será extremamente rápido. Isso difere significativamente de um sistema de banco de dados tradicional que às vezes é forçado a executar E / S enquanto mantém um bloqueio de página ou bloqueio de linha.


você poderia explicar por que isso aumenta a simultaneidade? Desculpe se estou perdendo o óbvio aqui.
batbrat

@batbrat: considere dois clientes que tentam gravar simultaneamente em coleções diferentes no mesmo banco de dados. Com um bloqueio de banco de dados, um dos clientes precisará aguardar o outro terminar antes que sua gravação possa ocorrer. Com um bloqueio de coleção, os dois clientes podem escrever ao mesmo tempo. Isso é o que se entende por aumento de simultaneidade. Obviamente, se os dois clientes tentarem gravar na mesma coleção, será necessário aguardar.
Jrullmann # 03/14

2

"No MongoDB, uma operação em um único documento é atômica" - Essa é a coisa do passado

Na nova versão do MongoDB 4.0, você PODE:

No entanto, para situações que exigem atomicidade para atualizações em vários documentos ou consistência entre leituras para vários documentos, o MongoDB oferece a capacidade de executar transações de vários documentos em conjuntos de réplicas. As transações com vários documentos podem ser usadas em várias operações, coleções, bancos de dados e documentos. As transações com vários documentos fornecem uma proposta de "tudo ou nada". Quando uma transação é confirmada, todas as alterações de dados feitas na transação são salvas. Se alguma operação da transação falhar, a transação será interrompida e todas as alterações de dados feitas na transação serão descartadas sem nunca se tornarem visíveis. Até que uma transação seja confirmada, nenhuma operação de gravação na transação será visível fora da transação.

Embora existam poucas limitações para as operações Como e Que podem ser executadas.

Verifique o Mongo Doc. https://docs.mongodb.com/master/core/transactions/


1

Você pode implementar atualizações atômicas de várias chaves (transação serializável) no lado do cliente se o seu armazenamento suportar a linearização por chave e comparar e definir (o que é verdade para o MongoDB). Essa abordagem é usada no Percolator do Google e no CockroachDB, mas nada impede você de usá-lo com o MongoDB.

Eu criei uma visualização passo a passo dessas transações. Espero que ajude você a entendê-los.

Se você está bem com o nível de isolamento confirmado por leitura, faz sentido dar uma olhada nas transações RAMP de Peter Bailis. Eles também podem ser implementados para o MongoDB no lado do cliente.

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.