Qu'est-ce que MongoDB n'était pas conforme à ACID avant la v4?

226

Je ne suis pas un expert en bases de données et je n'ai pas d'expérience en informatique, alors soyez indulgent avec moi. Je veux connaître les types de choses négatives du monde réel qui peuvent se produire si vous utilisez une ancienne version de MongoDB avant la v4 , qui n'était pas conforme à ACID . Cela s'applique à toute base de données non conforme ACID.

Je comprends que MongoDB peut effectuer des opérations atomiques , mais qu'il ne "prend pas en charge le verrouillage traditionnel et les transactions complexes", principalement pour des raisons de performances. Je comprends également l'importance des transactions de base de données, et l'exemple lorsque votre base de données est pour une banque, et que vous mettez à jour plusieurs enregistrements qui doivent tous être synchronisés, vous voulez que la transaction revienne à l'état initial s'il y a un panne de courant, donc le crédit est égal à l'achat, etc.

Mais quand j'entre dans des conversations sur MongoDB, ceux d'entre nous qui ne connaissent pas les détails techniques de la façon dont les bases de données sont réellement implémentées commencent à lancer des déclarations comme:

MongoDB est bien plus rapide que MySQL et Postgres, mais il y a une toute petite chance, comme 1 sur un million, qu'il "ne sauvegarde pas correctement".

Cette partie "ne sauvegardera pas correctement" fait référence à cette compréhension: s'il y a une coupure de courant juste au moment où vous écrivez sur MongoDB, il y a une chance pour un enregistrement particulier (disons que vous suivez les pages vues dans les documents avec 10 attributs chacun), que l'un des documents n'a enregistré que 5 des attributs ... ce qui signifie qu'avec le temps, vos compteurs de pages vues seront "légèrement" éteints. Vous ne saurez jamais de combien, vous savez qu'ils seront corrects à 99,999%, mais pas à 100%. En effet, à moins que vous n'en ayez spécifiquement fait une opération atomique mongodb , l'opération n'est pas garantie d'avoir été atomique.

Donc ma question est, quelle est la bonne interprétation de quand et pourquoi MongoDB peut ne pas "enregistrer correctement"? Quelles parties d'ACID ne satisfont-elles pas, et dans quelles circonstances, et comment savoir quand ces 0,001% de vos données sont désactivées? Cela ne peut-il pas être résolu d'une manière ou d'une autre? Sinon, cela semble signifier que vous ne devriez pas stocker des choses comme votre userstable dans MongoDB, car un enregistrement pourrait ne pas être sauvegardé. Mais là encore, cet utilisateur au 1/1 000 000 pourrait simplement avoir besoin de "réessayer de s'inscrire", non?

Je cherche juste peut-être une liste de quand / pourquoi des choses négatives se produisent avec une base de données non conforme ACID comme MongoDB, et idéalement s'il y a une solution de contournement standard (comme exécuter un travail en arrière-plan pour nettoyer les données, ou utiliser uniquement SQL pour cela, etc.) .

Lance Pollard
la source

Réponses:

133

Une chose que vous perdez avec MongoDB est les transactions multi-collections (table). Les modificateurs atomiques dans MongoDB ne peuvent fonctionner qu'avec un seul document.

Si vous devez supprimer un article de l'inventaire et l'ajouter à la commande de quelqu'un en même temps, vous ne pouvez pas. À moins que ces deux choses - inventaire et commandes - n'existent dans le même document (ce qu'elles n'existent probablement pas).

J'ai rencontré ce même problème dans une application sur laquelle je travaille et j'avais deux solutions possibles au choix:

1) Structurez vos documents du mieux que vous pouvez et utilisez les modificateurs atomiques du mieux que vous le pouvez et pour le bit restant, utilisez un processus d'arrière-plan pour nettoyer les enregistrements qui peuvent être désynchronisés. Par exemple, je supprime des éléments de l'inventaire et les ajoute à un tableau reserveInventory du même document à l'aide de modificateurs atomiques.

Cela me permet de toujours savoir que les articles ne sont PAS disponibles dans l'inventaire (car ils sont réservés par un client). Lorsque le client est sorti, je retire les articles de l'inventaire réservé. Ce n'est pas une transaction standard et puisque le client peut abandonner le panier, j'ai besoin d'un processus d'arrière-plan pour parcourir et trouver les paniers abandonnés et replacer l'inventaire réservé dans le pool d'inventaire disponible.

C'est évidemment loin d'être idéal, mais c'est la seule partie d'une grande application où mongodb ne répond pas parfaitement au besoin. De plus, il fonctionne parfaitement jusqu'à présent. Cela peut ne pas être possible pour de nombreux scénarios, mais en raison de la structure du document que j'utilise, il convient bien.

2) Utilisez une base de données transactionnelle conjointement avec MongoDB. Il est courant d'utiliser MySQL pour fournir des transactions pour les choses qui en ont absolument besoin tout en laissant MongoDB (ou tout autre NoSQL) faire ce qu'il fait le mieux.

Si ma solution de # 1 ne fonctionne pas sur le long terme, je vais étudier plus avant la combinaison de MongoDB avec MySQL mais pour l'instant # 1 convient bien à mes besoins.

Bryan Migliorisi
la source
27
" Les modificateurs atomiques dans MongoDB ne peuvent fonctionner qu'avec une seule collection " => Je pense que vous vouliez dire "contre un seul document ".
assylias
2
Excellente information, généralement une excellente réponse à l'exception de suggérer d'utiliser MySQL.
Doug Molineux
״ Une chose que vous perdez avec MongoDB est les transactions multi-collections (table). Les modificateurs atomiques dans MongoDB ne peuvent fonctionner qu'avec un seul document ״ de mongo doc ( docs.mongodb.com/v3.2/core/write-operations-atomicity ): "Dans MongoDB, une opération d'écriture est atomique au niveau d'un seul document, même si l'opération modifie plusieurs documents incorporés dans un seul document. "
yoav.str
5
Le manque de transactions ACID multi-documents n'est plus le cas. MongoDB a annoncé son arrivée en v4.0. Voir mongodb.com/blog/post/multi-document-transactions-in-mongodb
Grigori Melnik
1
Pour l'instant, puisque MongoDB 4.0 est conforme à ACID mongodb.com/transactions avec des transactions multi-documents. Jetez un œil à mongodb.com/blog/post/…
Ratah
134

Il n'est en fait pas correct que MongoDB ne soit pas compatible ACID. Au contraire, MongoDB est compilateur ACID au niveau du document .

Toute mise à jour d'un document unique est

  • Atomic: il complète complètement ou il ne fait pas
  • Cohérent: aucun lecteur ne verra une mise à jour "partiellement appliquée"
  • Isolé: encore une fois, aucun lecteur ne verra une lecture "sale"
  • Durable: (avec le souci d'écriture approprié)

Ce que MongoDB n'a pas, ce sont les transactions , c'est-à-dire les mises à jour de plusieurs documents qui peuvent être annulées et sont conformes à ACID.

Notez que vous pouvez créer des transactions en plus des mises à jour conformes à ACID dans un seul document, en utilisant la validation en deux phases .

William Z
la source
3
Notez que les transactions de validations en deux phases ne sont pas conformes à ACID. Pour une raison quelconque, j'ai déduit le contraire jusqu'à ce que je suive le lien.
Justin C
1
Il y a une question sur la durabilité de MongoDB distribué au niveau du document, quelle que soit la configuration du problème d'écriture. L'outil open-source Jepsen a constaté que les données peuvent être perdues face à une partition réseau, même avec le problème d'écriture MAJORITY. Voir l'article ici: aphyr.com/posts/284-call-me-maybe-mongodb
jrullmann
9
Avoir ACID au niveau d'un document unique qui équivaut en quelque sorte à un seul enregistrement dans le SGBDR n'est pas utile dans de nombreux cas. Le terme de transaction ne se rapporte pas à une table unique, et vous pouvez même avoir un mécanisme de validation en deux phases et impliquer plusieurs XAResource, donc se référer au document unique comme étant conforme à ACID est quelque peu problématique, à mon humble avis.
Yair Zaslavsky
5
D'accord avec Yair. "Conforme à l'ACID au niveau du document" n'est pas un argument de vente. Cela signifie simplement "non conforme à ACID". ACID n'a jamais été conçu pour être "une seule ligne / document / entité". Il s'agit de garder vos données cohérentes dans toute la base de données.
joshua.paling
34

Une bonne explication est contenue dans "Starbucks n'utilise pas la validation en deux phases" .

Il ne s'agit pas de bases de données NoSQL, mais cela illustre le fait que parfois vous pouvez vous permettre de perdre une transaction ou d'avoir temporairement votre base de données dans un état incohérent.

Je ne considérerais pas que c'est quelque chose qui doit être "corrigé". Le correctif consiste à utiliser une base de données relationnelle compatible ACID. Vous choisissez une alternative NoSQL lorsque son comportement répond aux exigences de votre application.

duffymo
la source
1
Comme toute analogie, elle a ses limites. Dans le logiciel, il est facile de créer de nouvelles baies [caissiers] et de les faire traiter chacune des transactions synchrones, alors que le coût réel de cela serait ridiculement cher.
HRJ
16

Je pense que d'autres personnes ont déjà donné de bonnes réponses. Cependant, je voudrais ajouter qu'il existe des bases de données ACID NOSQL (comme http://ravendb.net/ ). Ce n'est donc pas seulement la décision NOSQL - pas d'ACID vs Relationnel avec ACID ....

SubGate
la source
1
merci @subGate. quelqu'un là-bas qui peut partager son expérience avec ravenDB et si cela répond effectivement à l'exigence?
Nir Pengas du
12

"ne sauvegarde pas correctement" pourrait signifier:

  1. Par défaut, MongoDB n'enregistre pas immédiatement vos modifications sur le lecteur. Il est donc possible que vous disiez à un utilisateur que "la mise à jour a réussi", qu'une coupure de courant se produit et que la mise à jour est perdue. MongoDB fournit des options pour contrôler le niveau de «durabilité» des mises à jour. Il peut attendre que les autres répliques reçoivent cette mise à jour (en mémoire), attendre que l'écriture se produise dans le fichier journal local, etc.

  2. Il n'y a pas de mises à jour "atomiques" faciles pour plusieurs collections et même plusieurs documents dans la même collection. Ce n'est pas un problème dans la plupart des cas, car il peut être contourné avec la validation en deux phases ou la restructuration de votre schéma afin que les mises à jour soient apportées à un seul document. Voir cette question: Bases de données de documents: données redondantes, références, etc. (MongoDB en particulier)

Sergey
la source
10

Depuis MongoDB v4.0, les transactions ACID multi-documents doivent être prises en charge. Grâce à l'isolement des instantanés, les transactions fourniront une vue globalement cohérente des données et appliqueront une exécution tout ou rien pour maintenir l'intégrité des données.

Ils se sentent comme des transactions du monde relationnel, par exemple:

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()

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

Grigori Melnik
la source
La première version candidate de MongoDB4.0 est sortie - linkedin.com/pulse/mongodb-40-rc0-now-available-grigori-melnik
Grigori Melnik
5

Veuillez lire les propriétés ACID pour mieux comprendre.

Vous trouverez également dans la documentation MongoDB une question et une réponse .

MongoDB n'est pas compatible ACID. Lisez ci-dessous pour une discussion sur la conformité ACID.

  1. MongoDB est Atomique au niveau du document uniquement. Il ne correspond pas à la définition de l'atome que nous connaissons des systèmes de bases de données relationnelles, en particulier le lien ci-dessus. En ce sens, MongoDB n'est pas conforme au A d'ACID.
  2. MongoDB est Cprésent par défaut. Cependant, vous pouvez lire à partir de serveurs secondaires dans un jeu de réplicas. Vous ne pouvez avoir une cohérence éventuelle que dans ce cas. Ceci est utile si cela ne vous dérange pas de lire des données légèrement obsolètes.
  3. MongoDB ne garantit pas la Isolation (encore une fois selon la définition ci-dessus):
  1. Pour les systèmes avec plusieurs lecteurs et écrivains simultanés, MongoDB permettra aux clients de lire les résultats d'une opération d'écriture avant le retour de l'opération d'écriture.
  2. Si le mongod se termine avant la validation du journal, même si une écriture revient avec succès, les requêtes peuvent avoir des données lues qui n'existeront pas après le redémarrage du mongod.

Cependant , MongoDB modifie chaque document de manière isolée (pour les insertions et les mises à jour); au niveau du document uniquement, pas sur les transactions multi-documents.

  1. En ce qui concerne l' Durability - vous pouvez configurer ce comportement avec l' write concernoption, pas sûr cependant. Peut-être que quelqu'un sait mieux.

Je crois que des recherches sont en cours pour déplacer NoSQL vers des contraintes ACID ou similaires. C'est un défi car les bases de données NoSQL sont généralement plus rapides et les contraintes ACID peuvent ralentir considérablement les performances.

Ely
la source
4

La seule raison pour laquelle atomic modifie le travail par rapport à une seule collection est que les développeurs de mongodb ont récemment échangé un verrou de base de données avec un verrou en écriture pour l'ensemble de la collection. Décider que l'augmentation de la concurrence ici valait le compromis. Au fond, mongodb est un fichier mappé en mémoire: ils ont délégué la gestion du pool de tampons au sous-système vm de la machine. Parce qu'il est toujours en mémoire, ils peuvent s'en tirer avec des verrous très bien définis: vous effectuerez des opérations en mémoire uniquement tout en le maintenant, ce qui sera extrêmement rapide. Cela diffère considérablement d'un système de base de données traditionnel qui est parfois obligé d'effectuer des E / S tout en maintenant un verrou de page ou un verrou de ligne.

joeshmoe
la source
pourriez-vous expliquer pourquoi cela augmente la simultanéité? Désolé si je manque l'évidence ici.
batbrat
@batbrat: considérez deux clients qui tentent d'écrire simultanément dans des collections différentes dans la même base de données. Avec un verrou de base de données, l'un des clients devra attendre que l'autre se termine avant que son écriture puisse se produire. Avec un verrou de collecte, les deux clients peuvent écrire en même temps. C'est ce que l'on entend par concurrence accrue. Bien sûr, si les deux clients tentent d'écrire dans la même collection, il faudra attendre.
jrullmann
2

"Dans MongoDB, une opération sur un seul document est atomique" - C'est la chose pour le passé

Dans la nouvelle version de MongoDB 4.0, vous POUVEZ:

Cependant, pour les situations qui nécessitent une atomicité pour les mises à jour de plusieurs documents ou une cohérence entre les lectures de plusieurs documents, MongoDB offre la possibilité d'effectuer des transactions multi-documents sur des jeux de réplicas. Les transactions multi-documents peuvent être utilisées sur plusieurs opérations, collections, bases de données et documents. Les transactions multi-documents fournissent une proposition «tout ou rien». Lorsqu'une transaction est validée, toutes les modifications de données apportées dans la transaction sont enregistrées. Si une opération de la transaction échoue, la transaction s'interrompt et toutes les modifications de données apportées dans la transaction sont ignorées sans jamais devenir visibles. Jusqu'à ce qu'une transaction soit validée, aucune opération d'écriture dans la transaction n'est visible en dehors de la transaction.

Bien qu'il y ait peu de limitations pour les opérations Comment et Quoi peuvent être effectuées.

Vérifiez le Mongo Doc. https://docs.mongodb.com/master/core/transactions/

Mysterious25K
la source
1

Vous pouvez implémenter des mises à jour atomiques multi-clés (transaction sérialisable) côté client si votre stockage prend en charge la linéarisation par clé et comparer et définir (ce qui est vrai pour MongoDB). Cette approche est utilisée dans Percolator de Google et dans CockroachDB mais rien ne vous empêche de l'utiliser avec MongoDB.

J'ai créé une visualisation étape par étape de ces transactions. J'espère que cela vous aidera à les comprendre.

Si vous êtes d'accord avec le niveau d'isolement validé en lecture, il est logique de jeter un coup d'œil sur les transactions RAMP par Peter Bailis. Ils peuvent également être implémentés pour MongoDB côté client.

rystsov
la source