ibphoenix
Vous êtes ici : Programmer > Firebird pour les experts - Episode 5 - Verrouillage et versions des enregistrements
IBPhoenix
Informations sur les services et produits autour de Firebird, le support technique proposés par IBPhoenix
Autres langues
- www.ibphoenix.com
- www.ibphoenix.cz
Blogs
- Paul Beach
- Dimitri Kuzmenko
- Philippe Makowski
Informations générales
- Accueil
- Contacts
Produits
- IBUndelete
- IBTransactionMonitor
- Pack développeur Firebird
- IBFirstAid
- IBAnalyst
- Firebird Goodies
- Firebird Appliances
- IBReplicator
- Firebird Book
- IBBackupSurgeon
- CD déploiement
- CD Développeurs
- FBScanner
Services
- Formation et Conseil
- Services et support

- Session de formation en mai 2008
- Support en français
- IBPhoenix et IBase.ru s’unissent pour créer IBPhoenix Russie
- 2 jours pour optimiser vos bases Firebird
- Mandriva s’associe à IBPhoenix pour supporter Firebird 2.0
- Formation Firebird

Connect !
Faire connaitre Firebird
Ils utilisent Firebird

Documentation
Documentation en français produite par le Projet Firebird

Informations diverses
Infos sur tout ce qui concerne la vie autour de Firebird

Maintenance
Quelques indications sur la maintenance des bases

Programmer
Astuces et informations sur la programmation pour Firebird.

Forum
(developpez.net)

SourceForge.net Logo

Firebird pour les experts - Episode 5 - Verrouillage et versions des enregistrements
par Ann Harrison publié chez IBPhoenix Research
vendredi 22 juillet 2005, par Sébastien Blanchard


Le contrôle de l’accès concurrentiel est le mécanisme qui permet aux utilisateurs de lire et d’écrire simultanément des données si chaque utilisateur a un accès complet à la base de données. Cet état est appelé "capacité de sérialisation". L’état de la base de données après qu’un groupe de transactions concurrentes soit terminé est le même que si chacune de ces transactions avaient été exécutées dans un ordre quelconque. Peu, voire aucun, système de base de données offre des transactions sérialisables en tant que mode par défaut.

Encore récemment, le mécanisme d’accès concurrentiel le plus courant était le verrouillage. Naturellement, puisque les transactions sont des choses électroniques imaginaires, elles ne mettent pas réellement les verrous en laiton sur les clusters du disque. Cependant, le système de base de données impose une discipline concernant l’accès aux données ; chaque enregistrement d’une transaction est enregistré en mémoire et aucune transaction ne peut entrer en conflit avec un autre niveau d’utilisation. Les transactions posent des verrous lorsqu’elles accèdent aux données et n’enlèvent jamais de verrou tant qu’elles ne sont pas validées soit par un "COMMIT" soit par un "ROLLBACK". La stratégie qui consiste à verrouiller de manière incrémentale les enregistrements et à les déverrouiller simultanément lorsque la transaction se termine est appelée "verrouillage en deux phases".

Le verrouillage

Les verrous d’écriture permettent d’éviter les écritures dites "sales".

Dans un système basé sur le verrouillage pour gérer l’accès concurrentiel aux données, lorsqu’une transaction modifie, insert ou supprime un enregistrement, elle commence par le verrouiller. Les verrous d’écriture sont exclusifs et seulement une transaction peut poser un verrou d’écriture à un instant T. Ce seul verrou permet d’éviter à deux transactions de modifier un même enregistrement en même temps et il satisfait généralement le plus bas niveau de concurrence. Une écriture "sale" pourrait apparaître comme suit :

  • Transaction A : lit un enregistrement concernant un employé et augmente le salaire.
  • Transaction B : lit le même enregistrement et lui donne une promotion.

Si les deux mises à jour de l’enregistrement sont effectuées simultanément, le résultat sans verrou d’écriture serait que l’employé bénéficiera soit d’une augmentation de salaire, soit d’une promotion mais pas les deux.

Les verrous de lecture

Dans une base de données verrouillée, lorsqu’une transaction lit un enregistrement, elle pose un verrou de lecture sur cet enregistrement. Plusieurs verrous de lecture peuvent cohabiter ensemble mais ne peuvent cohabiter avec des verrous d’écriture. Les verrous de lecture permettent d’éviter les lectures dites "sales". Une lecture "sale" permet à une transaction de voir les résultats non validés ("uncommited") d’une transaction concurrente.

  • Transaction A : lit un enregistrement concernant un employé et augmente le salaire.
  • Transaction B : lit le même enregistrement et ajoute son salaire au rapport du budget du département.
  • Transaction A : annule ses modifications ; la Transaction B a récupéré un faux total concernant le budget du département.

Lecture cohérente

Une transaction active dans une base de données voit toujours le même état de la base de données, à l’exception des modifications qu’elle a pu apporter elle-même. Cet état est appelé "lecture cohérente" si, lorsqu’une transaction lit deux fois le même enregistrement, elle voit les mêmes données à l’exception de celles qu’elle a modifiées elle-même. Si une transaction lit l’ensemble des enregistrements d’une table à un instant T, elle verra exactement le même nombre d’enregistrements avec les mêmes contenus lors d’une relecture à un instant T+1, à l’exception des changements qu’elle a effectués elle-même. Les verrous de lecture et d’écriture seuls ne produisent pas de lectures cohérentes. Considérons l’exemple suivant :

  • Transaction A : compte le nombre d’employés d’un département Z, en verrouillant chaque enregistrement en lecture.
  • Transaction B : ajoute un enregistrement correspondant à un nouvel employé dans le département Z, avec un verrou d’écriture sur cet enregistrement - OU - met à jour le département d’un employé en le déplaçant dans le département Z.
  • Transaction B : valide la transaction et enlève ses verrous.
  • Transaction A : compte le nombre d’employés du département Z et trouve un total différent du premier comptage.

Afin de s’assurer que ces lectures puissent être répétées, la transaction A doit verrouiller plus que les enregistrements existants, quelque chose de plus abstrait. Ces verrous abstraits sont appelés "verrous prédicats" ou "verrous d’existence" ; ce sont des verrous qui permettent d’ajouter quelque chose de nouveau à un ensemble de résultats, soit en insérant un nouvel enregistrement, soit en modifiant un enregistrement existant. Il répond ainsi au critère de cohérence d’un ensemble de données.

Les verrous prédicats peuvent être implémentés comme des verrous sur les chemins d’accès aux enregistrements.

Si le département est un champ indexé, la transaction A pourra poser un verrou de lecture sur la partie de cette index qui pointe sur les enregistrements associés au département Z. Ensuite, lorsque la transaction B voudra créer une nouvelle entrée possédant cet index, elle rencontrera un conflit de verrouillage et attendra que la transaction A se termine et enlève ses verrous.

Si le département n’est pas un champ indexé, la transaction A posera un verrou sur toute la table des employés, empêchant ainsi d’ajouter des enregistrements à cette table. Aucun employé ne pourra être ni ajouté, ni modifié, ni supprimé tant que la transaction A ne sera pas terminée.

Sérialisation des transactions

Les verrous de lecture, d’écritures et de prédicats produisent des transactions sérialisables. Cependant, cela implique un certain nombre de tables verrouillées ainsi que certaines impasses ou controverses.

Taille d’un table verrouillée

Même si les verrous sont de petites choses temporaires, la lecture de plusieurs millions d’enregistrements implique la création de très nombreux verrous. C’est pour cette raison que de nombreux systèmes qui utilisent les verrous de lecture emploient des stratégies appelées "verrouillage par rétrogradation ou promotion".

Controverse et impasses

Une transaction importante qui utilise des verrous de lecture en deux phases peut facilement bloquer tous ceux qui souhaitent écrire dans la base de données. Inversement, ceux qui souhaitent écrire peuvent également poser des verrous qui bloquent des pages, impliquant des impasses. La conséquence est que les performances sont souvent plus mauvaises lorsque les transactions entrent en concurrence et utilisent le verrouillage à deux phases que lorsque les transactions étaient réellement exécutées une par une.

Contrôle de l’accès concurrentiel multi-versions

Firebird utilise comme stratégie les versions des enregistrements au lieu d’écrire des verrous et les logs des transactions. L’utilisation des versions des enregistrements dans les transactions est décrite ici.

Verrous d’écriture - Ecriture "sales"

Chaque version d’enregistrement est marquée avec la version de la transaction qui l’a créé. Toutes les transactions connaissent celles qui sont actives. Aucune transaction ne peut modifier ou supprimer un enregistrement dont la version de la transaction la plus récente n’est pas une transaction validée. Les écritures sales sont donc impossibles.

Verrous de lecture - Lectures "sales"

Etant donné que les enregistrements sont marqués avec leur version et que chaque transaction connaît les versions des transactions actives, aucune transaction ne peut lire une version d’un enregistrement créé par une transaction active. Les lectures "sales" sont donc impossibles.

Lecture répétées

Ci-dessous les différents modes de transaction. Firebird supporte trois modes orthogonaux :

  • consistency/concurrency/read committed,
  • wait/no wait,
  • snapshot/no snapshot.

Cet article décrit la seule transaction 100% Firebird : concurrency, wait, snapshot. Les transactions cohérentes verrouillent les tables et sont particulièrement ennuyeuses à décrire. Le mode "read commited" empêche les lectures répétées parce que dès que les données ont été validées, elles deviennent immédiatement accessibles aux transactions actives. Avec l’option "no wait", les transactions déclenchent une erreur dès qu’elles rencontrent le moindre conflit. Les transactions "no snapshot" lisent seulement la dernière version validée d’un enregistrement et ne sont utiles qu’avec le mode "read commited" (ndt : correspond à l’option "rec_version").

Une transaction en mode "concurrency", "wait", "snapshot" permet des lectures répétées. Lorsque la transaction démarre, elle crée une liste de toutes les transactions validées, et quand elle accède à un enregistrement, elle remonte dans l’historique de ses versions jusqu’à en trouver une dont le marqueur de transaction appartient à la liste des transactions validées. Les modifications faites par les transactions concurrentes sont ignorées.

Sérialisation des transactions

Contrairement aux systèmes basés sur des verrous, un système de contrôle des accès concurrentiels multi-générationnel permet des lectures répétées sans être complètement sérialisable. Voici deux anomalies qui affectent Firebird :

* Echanges

Un échange survient quand deux transactions utilisent des données provenant d’enregistrements différents et applique leurs modifications dans l’ordre inverse. Un exemple sera plus parlant :

Le problème est de s’assurer que tous les employés ayant le même statut ont le même salaire, indépendamment de leur sexe. Une solution consiste à lire les enregistrements concernant les hommes pour chaque statut et de modifier les enregistrements concernant les femmes en utilisant les salaires des hommes. Une autre solution, plus économique pour l’entreprise consiste à modifier le salaire des hommes à partir de celui des femmes.

  • Transaction A : lire les salaires des hommes, modifier ceux des femmes.
  • Transaction B : lire les salaires des femmes, modifier ceux des hommes.

Le résultat est que la différence de salaires est inversée mais existe toujours. Ce problème n’arriverait pas si les deux transactions étaient actives séparément. Les transactions n’entrent pas en conflit parce que chaque enregistrement n’est modifié qu’une seule fois. Les modifications effectuées par la transaction A ne sont pas visibles parce que lorsque la transaction B essaie de lire un enregistrement qui a été modifié par A, elle lit automatiquement la dernière version validée, et inversement...

La solution, quand on est au courant que cette erreur peut arriver, est de s’arranger pour bien choisir l’ordre dans lequel on copie les données d’un enregistrement vers l’autre.

* Problèmes à l’insertion

A l’insertion, des problèmes peuvent aussi apparaître quand deux transactions concurrentes modifient des données. Exemple :

Chaque transaction n’a vu que ses propres modifications donc chaque comptage a ignoré les enregistrements insérés par l’autre transaction. Si les transactions avaient été exécutées en série, les résultats auraient été :

La solution consiste à utiliser un index unique sur chaque colonne qui peut stocker le nombre (ou le maximum) des valeurs de la table. Les index uniques sont correctement exploités même lorsque les transactions impliquées ne peuvent pas voir les enregistrements des autres transactions.

L’article original en langue anglaise se trouve à : http://ibphoenix.com/main.nfs ?a=ibphoenix&s=1122013419:87484&page=ibp_expert5


Dans la même rubrique :
Client léger pour applications Delphi avec Firebird comme base d’objets et d’applications
Questions Techniques diverses
2 routines de dates/heures dans les procédures stockées
Firebird pour les experts - Episode 1 - Les Index
Definition de l’OIT
Champs Double Precision et Dialect 3
Dll pour savoir si Firebird ou Interbase sont installés
Les outils pour se connecter à Firebird
Exemples d’utilisation de procédures stockées avec Firebird/Interbase
Unified Interbase

Sur le web :
[Firebird][OpenSource][SGBD] Firebird 2.0 Language Ref. Update
[Firebird][OpenSource][SGBD] Trouver les enregistrements absent d'une table entre deux bases de données
[Firebird][OpenSource][SGBD] Les premiers Rendez-vous Firebird le 12 juillet à Amiens dans le cadre des Rencontres Mondiales des Logiciels Libres
[Firebird][OpenSource][SGBD] IBPhoenix et IBase.ru s’unissent pour créer IBPhoenix Russie
[Firebird][OpenSource][SGBD] Les documents de la conférence firebird sont en ligne
[OpenSource] Pour commencer l’année
Firebird 2.1 est là
[Firebird][OpenSource][SGBD] Firebird 2.1 est là




Proposer un article | Nous contacter | Plan du site | Admin | Accueil