web-dev-qa-db-fra.com

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

Je ne suis pas un expert en bases de données et je n'ai aucune formation en informatique, alors supportez-moi. Je veux connaître les types de choses négatives du monde réel pouvant survenir si vous utilisez un ancien version de MongoDB antérieure à la v4 , qui n'étaient pas ACIDE conforme. Cela s'applique à toute base de données non conforme ACID.

Je comprends que MongoDB peut exécuter Atomic Operations , mais qu’elles ne "prennent pas en charge les opérations de verrouillage traditionnelles et complexes", principalement pour des raisons de performances. Je comprends également l’importance des transactions de base de données et des exemples de cas où votre base de données est destinée à une banque et que vous mettez à jour plusieurs enregistrements qui doivent tous être synchronisés. Vous souhaitez que la transaction revienne à l’état initial si un panne de courant, crédit égal à achat, etc.

Mais lorsque je discute de MongoDB, ceux d'entre nous qui ne connaissent pas les détails techniques de la mise en œuvre effective des bases de données commencent par lancer des déclarations telles que:

MongoDB est bien plus rapide que MySQL et Postgres, mais il y a une chance infime, comme 1 sur 1 000, de "ne pas enregistrer correctement".

Cette partie "ne sauvegardera pas correctement" fait référence à cette interprétation: si une coupure de courant survient au moment où vous écrivez dans MongoDB, il est possible qu'un enregistrement particulier (par exemple, vous suivez les pages vues dans des documents comportant 10 attributs). chacun des documents), que l’un des documents n’a sauvegardé que 5 des attributs… ce qui signifie que vos compteurs de pages vues seront avec le temps "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'ayez spécifiquement spécifié cela comme une opération opération atomique mongodb , l'opération n'a pas été garantie comme étant atomique.

Ma question est donc la suivante: quelle est l'interprétation correcte du moment et de la raison pour laquelle MongoDB ne peut pas "enregistrer correctement"? Quelles parties d'ACID ne satisfont-elles pas et dans quelles circonstances, et comment savoir quand ces données sont à 0,001% inactives? Cela ne peut-il pas être réparé d'une manière ou d'une autre? Sinon, cela semble signifier que vous ne devriez pas stocker d'éléments tels que votre table users dans MongoDB, car un enregistrement risque de ne pas être enregistré. Mais là encore, ce 1/000.000 utilisateur pourrait juste avoir besoin de "essayer de vous réinscrire", non?

Je cherche peut-être une liste des raisons pour lesquelles des événements négatifs surviennent avec une base de données non conforme ACID telle que MongoDB, et idéalement s’il existe une solution standard (par exemple, exécuter un travail en arrière-plan pour nettoyer les données, ou utiliser uniquement SQL pour cela, etc.). .

220
Lance Pollard

Une chose que vous perdez avec MongoDB est des 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 en même temps à la commande de quelqu'un, vous ne pouvez pas. À moins que ces deux choses - inventaire et commandes - existent dans le même document (ce qui n’est probablement pas le cas).

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

1) Structurez vos documents du mieux possible et utilisez les modificateurs atomiques de votre mieux. Pour le bit restant, utilisez un processus en arrière-plan pour nettoyer les enregistrements éventuellement désynchronisés. Par exemple, je supprime des éléments de l'inventaire et les ajoute à un tableau reservedInventory 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 supprime ensuite les éléments de l’inventaire réservé. Ce n'est pas une transaction standard et comme le client peut abandonner le panier, il me faut un processus d'arrière-plan pour rechercher des paniers abandonnés et ramener l'inventaire réservé dans le pool d'inventaire disponible.

Ceci n’est évidemment pas idéal, mais c’est la seule partie d’une grande application où mongodb ne convient pas parfaitement. De plus, cela fonctionne parfaitement jusqu'à présent. Cela peut ne pas être possible dans de nombreux scénarios, mais en raison de la structure de document que j'utilise, cela convient bien.

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

Si ma solution de # 1 ne fonctionne pas à long terme, j'examinerai plus avant la combinaison de MongoDB avec MySQL mais, pour le moment, # 1 convient parfaitement à mes besoins.

129
Bryan Migliorisi

En réalité, il n’est pas exact que MongoDB ne soit pas compatible ACID. Au contraire, MongoDB est ACID-compilant au niveau du document.

Toute mise à jour d'un seul document est

  • Atomic: soit complète ou non
  • 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, c’est transactions - c’est-à-dire des mises à jour de plusieurs documents pouvant être annulées et supprimées. sont conformes à ACID.

Notez que vous pouvez créer des transactions au-dessus des mises à jour compatibles ACID pour un seul document, par à l'aide de la validation en deux phases .

131
William Z

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

Il ne s'agit pas de bases de données NoSQL, mais cela montre bien que parfois, vous pouvez vous permettre de perdre une transaction ou que votre base de données est temporairement incohérente.

Je ne considérerais pas que ce soit 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.

34
duffymo

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

16
SubGate

"ne sauvera pas correctement" pourrait signifier:

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

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

12
Sergey

À partir de MongoDB v4.0, les transactions ACID multi-documents doivent être prises en charge. Grâce à l'isolation des instantanés, les transactions fourniront une vue cohérente des données et imposeront une exécution tout ou rien pour préserver 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

9
Grigori Melnik

Veuillez lire à propos de propriétés ACID pour mieux comprendre.

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

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

  1. MongoDB est Atomic au niveau du document uniquement. Il ne correspond pas à la définition de l'atome que nous connaissons des systèmes de base de données relationnelle, en particulier du lien ci-dessus. En ce sens, MongoDB n'est pas conforme au A de ACID.
  2. MongoDB est Consitent par défaut. Cependant, vous pouvez lire à partir de serveurs secondaires d'un jeu de réplicas. Vous pouvez uniquement avoir une cohérence éventuelle dans ce cas. Ceci est utile si vous ne voulez pas lire des données légèrement obsolètes.
  3. MongoDB ne garantit pas Isolation (toujours selon la définition ci-dessus):
  1. Pour les systèmes comportant plusieurs lecteurs et graveurs 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 l'écriture est renvoyée avec succès, les requêtes peuvent avoir lu des données qui n'existeraient 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 des transactions multi-documents.

  1. En ce qui concerne Durability - vous pouvez configurer ce comportement avec le write concern _ option, 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. Ceci est un défi, car les bases de données NoSQL sont généralement plus rapides (et) et les contraintes ACID peuvent considérablement ralentir les performances.

4
Ely

La seule raison pour laquelle Atomic modifie son travail par rapport à une collection unique est que les développeurs de mongodb ont récemment échangé un verrou de base de données avec un verrou en écriture pour toute la collection. Décider que la simultanéité accrue en valait la peine. À la base, mongodb est un fichier mappé en mémoire: ils ont délégué la gestion du pool de mémoire tampon au sous-système vm de la machine. Comme ils sont toujours en mémoire, ils peuvent se débrouiller avec des verrous très précis: vous effectuerez des opérations en mémoire tout en les tenant, 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 tenant un pagelock ou un verrou de ligne.

4
joeshmoe

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

Dans la nouvelle version de MongoDB 4.0 , vous POUVEZ:

Cependant, pour les situations nécessitant l'atomicité des mises à jour de plusieurs documents ou la 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 effectuées dans la transaction sont enregistrées. Si une opération de la transaction échoue, la transaction échoue et toutes les modifications de données effectué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/

2
Mysterious25K

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

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

Si le niveau d'isolement validé en lecture vous convient, jetez un coup d'œil à transactions RAMP par Peter Bailis. Ils peuvent également être implémentés pour MongoDB côté client.

1
rystsov