Blog ENI : Toute la veille numérique !
🐠 -25€ dès 75€ 
+ 7 jours d'accès à la Bibliothèque Numérique ENI. Cliquez ici
Accès illimité 24h/24 à tous nos livres & vidéos ! 
Découvrez la Bibliothèque Numérique ENI. Cliquez ici
  1. Livres et vidéos
  2. MongoDB
  3. Les transactions multidocuments
Extrait - MongoDB Comprendre et optimiser l'exploitation de vos données (avec exercices et corrigés)
Extraits du livre
MongoDB Comprendre et optimiser l'exploitation de vos données (avec exercices et corrigés) Revenir à la page d'achat du livre

Les transactions multidocuments

Introduction

Les transactions multidocuments constituent indubitablement une des nouveautés majeures de la version 4 de MongoDB. Elles garantissent l’intégrité des données, car si une seule des opérations qu’elles contiennent échoue, alors c’est toute la transaction qui échoue ; il est ainsi impossible de laisser notre base de données dans un état intermédiaire qui menacerait la cohérence même des informations qu’elle contient. On dit pour cette raison qu’une transaction est atomique (c’est tout ou rien).

Ces transactions sont indépendantes les unes des autres et exécutées de manière parfaitement isolée, ce qui signifie que tout changement intervenant durant une transaction ne sera visible à l’extérieur de celle-ci qu’une fois qu’elle sera validée et ses données enregistrées de façon durable.

Nous venons d’énoncer ce que l’on appelle dans le jargon des bases de données les « propriétés ACID » : Atomicité - Cohérence - Isolation - Durabilité.

Apparues avec la version 4.0 de MongoDB et ciblant uniquement les replica sets, les transactions se sont étendues aux clusters shardés dans la version 4.2, où elles ont été rebaptisées transactions distribuées.

Créons à présent notre première transaction ! Pour ne pas avoir à créer de replica set local, nous allons utiliser un cluster sur Atlas, la solution...

Les sessions

Transactions et sessions sont très fortement couplées comme vous avez pu le constater sur le code précédent : une transaction est exécutée dans le cadre d’une session, qui elle ne peut avoir plus d’une transaction ouverte simultanément. L’interruption d’une session, souhaitée ou non, conduit à l’annulation de toute transaction en cours sur celle-ci.

Voyons les différentes parties liées à la session. Tout d’abord sa création depuis la connexion en cours à la base de données (méthode getMongo()) :

var session = db.getMongo().startSession(); 

Ensuite, le démarrage d’une transaction liée à cette session nouvellement créée :

session.startTransaction(); 

Notre transaction est ensuite validée ou bien interrompue. Pour la valider, il faut utiliser commitTransaction comme ceci :

session.commitTransaction() 

Pour interrompre une transaction et donc ne réaliser aucune des opérations qui s’y trouvaient, il faut utiliser abortTransaction :

session.abortTransaction() 

Enfin, il faut fermer la session, quel qu’ait pu être le destin de notre transaction :

session.endSession() 

Depuis la session, nous avons également pu récupérer des liens vers nos collections et les stocker dans des variables, le tout à...

Un exemple : la transaction bancaire

Excusez par avance le manque d’originalité de l’exemple qui va suivre, mais le scénario de la transaction bancaire reste LE cas le plus souvent utilisé (et le plus parlant !) lorsque l’on évoque les transactions, surtout dans les bases de données relationnelles, il est vrai ! Nous allons commencer par créer une nouvelle base de données nommée mabanque. Sur notre cluster Atlas, nous allons pour cela cliquer sur le bouton Create Database avant de renseigner son nom ainsi que celui de la toute première collection que nous allons créer dedans, à savoir comptes :

images/07EP11.png
images/07EP12.png

Une fois cette première collection créée, nous en créons une seconde, nommée cette fois mouvements. Si la première contient quelques informations élémentaires sur les comptes bancaires de nos clients fictifs (un numéro, un solde), la seconde journalise l’ensemble des flux financiers qui ont eu lieu sur ceux-ci à une date donnée. Il nous suffit pour cela de cliquer sur l’icône portant le signe « + » à côté du nom de notre base de données :

images/07EP13.png

Nous avons maintenant une base de données et ses deux collections prêtes à l’emploi, alimentons la collection comptes en exécutant des insertions depuis la ligne de commande MongoDB :

MongoDB Enterprise Cluster0-shard-0:PRIMARY> use mabanque; 
switched to db mabanque 
MongoDB Enterprise Cluster0-shard-0:PRIMARY> db.comptes.insertMany([ 
...     {"numcompte": "FR761111222233334444", "solde": 1000}, 
...     {"numcompte": "FR76111122223333555", "solde": 1000} 
... ]) 
{ 
       "acknowledged" : true, 
       "insertedIds" : [ 
               ObjectId("5cfbc47d68f49b169927fb96"), 
               ObjectId("5cfbc47d68f49b169927fb97") 
       ] 
} 

La collection comptes étant maintenant approvisionnée en documents, nous allons pouvoir nous atteler à la mise en œuvre...

Conflits d’écriture

Lorsqu’une transaction T1 s’apprête à effectuer des modifications sur un document, il se peut que celui-ci soit déjà en cours de modification par une transaction T2. Le cas échéant, un verrou (lock) est posé par T2 jusqu’à ce que cette transaction soit terminée. Si T1 n’arrive pas à obtenir de verrou sur le document sur lequel il est en concurrence avec T2 , elle patientera, mais échouera passé un délai de 5 millisecondes si elle ne peut pas s’accaparer les verrous.

Les verrous d’écriture ne sont pas les mêmes que les verrous de lecture, ils sont les seuls à pouvoir éventuellement générer des conflits. Ainsi, des documents en cours de modification par une transaction pourront être lus sans problème : ils apparaîtront simplement dans un état qui ne sera potentiellement pas le même que celui dans lequel ils seront une fois la transaction terminée. De même que la lecture d’un document n’entraînera pas le blocage d’une transaction s’apprêtant à en modifier l’état.

Limitation des transactions

Ce mécanisme présente quelques limites dans MongoDB :

  • La taille d’une transaction multidocument est limitée à 16 mégaoctets. Si elle dépasse cette taille, la transaction sera interrompue et les documents remis dans l’état initial.

  • La durée d’une transaction multidocument est limitée à 60 secondes. Passée cette durée, la transaction sera purement et simplement interrompue par MongoDB. Afin de contourner cette limite, il faut s’assurer que les bons index sont utilisés, que les requêtes sont optimisées et si cela ne suffit pas, il faudra scinder la transaction en parties de plus petite taille.

  • On ne peut pas créer ou supprimer une collection au sein d’une transaction, elle doit exister avant l’exécution de celle-ci. Il est également impossible de réaliser des opérations sur des index, que ce soit une suppression ou bien une création.

  • Les commandes d’administration sont interdites dans une transaction (createUser, getParameter, etc.).

  • Les lectures et les écritures sont interdites dans les collections local, admin ou encore config.

  • Les écritures dans les collections préfixées par system sont également interdites.

  • Les bonnes pratiques recommandent de ne pas modifier plus de 1000 documents au sein d’une même transaction....