Architecture de moteur ESE (moteur de stockage extensible)

 

S’applique à : Exchange Server 2007 SP3, Exchange Server 2007 SP2, Exchange Server 2007 SP1, Exchange Server 2007

Dernière rubrique modifiée : 2008-11-19

Les bases de données de boîtes aux lettres Exchange et la file d'attente sur les serveurs de transport Hub et les serveurs de transport Edge utilisent la base de données ESE (Extensible Storage Engine). Le moteur ESE se compose d'un gestionnaire de tables ISAM (Indexed Sequential Access Method) multi-utilisateur qui offre des fonctionnalités complètes en matière de langage de manipulation de données (DML) et de langage de définition de données (DDL). Le moteur ESE permet aux applications de stocker des enregistrements et de créer des index pour y accéder de différentes manières.

Il existe deux versions du moteur ESE :

  • ESENTI   Moteur de base de données pour Active Directory et de nombreux autres composants Microsoft Windows. Contrairement à d'autres versions du moteur ESE (qui utilisent des fichiers journaux de 5 Mo et des tailles de pages de 4 Ko), l'implémentation Active Directory de ESENT a recours à des fichiers journaux de 10 Mo et des pages de 8 Ko.

  • ESE98   Moteur de base de données utilisé par Exchange 2000 Server, Exchange Server 2003 et Exchange Server 2007.

  • Le moteur ESE était précédemment appelé Joint Engine Technology (JET) Blue. JET Blue ne doit pas être confondu avec la version de JET que l'on trouve dans Microsoft Access (appelée « JET Red »).

Transactions

ESE est un moteur de base de données sophistiqué, basé sur des transactions. Une transaction est une série d'opérations traitées comme une unité que l'on qualifie d'atomique (indivisible). Cela signifie que toutes les opérations d'une transaction sont exécutées ou enregistrées de manière permanente, ou bien qu'aucune ne l'est. Prenons l'exemple des opérations liées au transfert d'un message du dossier Boîte de réception vers le dossier Éléments supprimés. Le message est supprimé d'un dossier, ajouté à un autre et les propriétés des dossiers sont modifiées. En cas de défaillance, il ne serait pas souhaitable de se retrouver avec deux copies du message, aucune copie du tout ou des valeurs de propriétés de dossiers (telles que le nombre d'éléments) qui ne correspondent pas au contenu réel des dossiers.

C'est pour éviter ce genre de problème que le moteur ESE regroupe les opérations au sein d'une transaction. Il s'assure qu'aucune des opérations n'est appliquée de manière permanente tant que la transaction n'est pas validée dans le fichier de base de données. Une fois la validation effectuée, l'ensemble des opérations est appliqué de manière permanente.

Si un serveur ne répond plus, le moteur ESE assure également une récupération automatique au redémarrage du serveur et annule toute transaction non validée. Si une défaillance du moteur ESE survient avant qu'une transaction n'ait été validée, cette dernière est annulée dans son ensemble, comme si elle n'avait jamais été exécutée. Si le moteur ESE ne répond plus après validation de la transaction, cette dernière est conservée dans son ensemble et les clients peuvent voir les changements.

Transactions ACID

Des transactions telles que celles répertoriées dans la section précédente sont généralement appelées transactions ACID. ACID est un acronyme formé à l'aide des initiales des attributs suivants :

  • Atomique   Terme indiquant que toutes les modifications d'état liées à une transaction sont effectuées ou qu'aucune ne l'est. Les modifications d'état atomiques incluent les modifications de la base de données, ainsi que les messages et actions portant sur les transducteurs.

  • Cohérente   Terme indiquant qu'une transaction se traduit par une transformation acceptable de l'état de la base de données. Les actions exécutées dans le cadre du groupe d'opérations n'enfreignent aucune des contraintes d'intégrité associées à l'état. Il faut pour cela que la transaction soit un programme correct.

  • Isolée   Terme indiquant que, même si les transactions sont exécutées simultanément, il apparaît que, pour chaque transaction (t), les autres transactions ont été exécutées soit avant, soit après t mais pas les deux.

  • Durable   Les transactions validées sont conservées dans la base de données, même si le système cesse de réponde.

Banque de versions

La banque de versions permet au moteur ESE de suivre et de gérer les transactions en cours. Le moteur ESE peut ainsi réussir la partie Isolée et Cohérente du test ACID. La banque de versions gère une liste en mémoire des modifications apportées à la base de données.

Elle est utilisée dans les situations suivantes :

  • Annulation   Si une transaction doit être annulée, le système consulte la banque de versions pour obtenir la liste des opérations effectuées dans le cadre de la transaction. Toutes les opérations sont alors exécutées à l'inverse, ce qui permet d'annuler la transaction.

  • Détection des conflits en écriture   Si deux sessions différentes tentent de modifier le même enregistrement, la banque de versions remarque la seconde modification et la rejette.

  • Lectures répétitives   Lorsqu'une session lance une transaction, elle trouve toujours la même vue de la base de données, même si d'autres sessions modifient les enregistrements qu'elle visualise. Quand une session lit un enregistrement, le système consulte la banque de versions pour déterminer quelle version de l'enregistrement la session doit visualiser. Les lectures répétitives offrent un niveau d'isolement grâce auquel, une fois qu'un client a lancé une transaction, l'état de la base de données qu'il visualise correspond à l'état de la base avant lancement de la transaction, quelles que soient les modifications apportées par d'autres clients ou sessions. Les lectures répétitives sont implémentées à l'aide de la banque des versions. Grâce à une liste en mémoire des modifications apportées à la base de données, elle peut déterminer la vue qu'une session donnée doit obtenir pour un enregistrement.

  • Enregistrement d'image avant différé   Optimisation complexe grâce à laquelle le moteur ESE peut enregistrer moins de données que d'autres moteurs de bases de données similaires.

Isolement d'instantané

Une fois une transaction lancée, le moteur ESE garantit que la session affiche une image unique et cohérente de la base de données, telle qu'elle se présente au début de la transaction, avec ses propres changements en plus. Comme d'autres sessions peuvent également modifier les données et valider leurs transactions, ces changements sont invisibles pour n'importe quelle transaction lancée avant la validation. Un utilisateur peut modifier un enregistrement uniquement s'il en visualise la version la plus récente. Sinon, la mise à jour échoue et une condition d'erreur JET_errWriteConflict est signalée. Les versions antérieures à la transaction la plus récente sont automatiquement ignorées.

Le moteur ESE offre un niveau d'isolement de transaction appelé isolement d'instantané. Ce dernier permet aux utilisateurs d'accéder à la dernière ligne validée à l'aide d'une vue cohérente de la base de données sur le plan transitionnel. Il s'agit d'un algorithme de contrôle de la simultanéité décrit pour la première fois dans l'article intitulé A Critique of ANSI SQL Isolation Levels. Il est implémenté par le moteur ESE grâce à l'utilisation des lectures répétitives.

Structure de la base de données ESE

Toutes les données situées à l'intérieur du fichier de base de données au format RTF sont stockées dans des arborescences que l'on appelle arborescences B pour Balanced (équilibrées). Le terme « arborescence » fait référence à une disposition comparable à celle d'une structure de dossiers dans un système de fichiers, où une racine est le parent des éléments (pages de base de données) qui à leur tour sont les parents d'autres éléments. Les arborescences B sont conçues pour permettre un accès rapide aux données sur disque. Étant donné que la lecture à partir d'un disque et l'écriture sur un disque sont beaucoup plus lentes que la réalisation de ces opérations en mémoire, une arborescence B est divisée en pages de 8 Ko. Le moteur ESE peut ainsi obtenir les données dont il a besoin en ayant recours à un minimum d'opérations d'E/S sur disque. Une base de données ESE peut contenir jusqu'à 2^31 (2 exposant 31) pages de 8 Ko pour une taille totale maximale de base de données de 16 téraoctets. En réalité, la taille de la base de données n'est limitée que par votre capacité à sauvegarder, restaurer et effectuer d'autres opérations de maintenance (telles que la défragmentation en mode hors connexion et les réparations de base de données) au moment opportun.

Pages de base de données

La taille de la page dans le moteur ESE est définie par l'application qui l'utilise. Par exemple, ESE98 (Exchange 2000 et Exchange Server 2003) utilisent des pages de 4 Ko tandis qu'ESENT (Active Directory) utilise des pages de 8 Ko. Chacune de ces pages de 4 ou de 8 Ko contient des pointeurs vers d'autres pages ou vers les données réelles stockées dans l'arborescence B. Le pointeur et les pages de données sont mélangés dans le fichier.

Pour accroître les performances chaque fois que possible, les pages sont mises en cache dans un tampon mémoire le plus longtemps possible. Le nombre d'accès au disque est donc réduit. Chaque page commence par un en-tête de 40 octets composé des valeurs suivantes :

  • pgnoThis   Valeur indiquant le numéro de la page.

  • DbtimeDirtied   Valeur indiquant l'heure Dbtime à laquelle la page a été modifiée en dernier.

  • pgnoPrev   Valeur indiquant le numéro de la page gauche adjacente sur la feuille.

  • pgnoNext   Valeur indiquant le numéro de la page droite adjacente sur la feuille.

  • ObjidFDP   Valeur représentant l'ID d'objet d'une page spéciale de la base de données appelée Père de la page de données (FDP) et qui indique à quelle arborescence B la page appartient. La page FDP est utilisée pendant les réparations.

  • cbFree   Valeur indiquant le nombre d'octets disponibles dans la page.

  • cbUncommittedFree   Valeur indiquant le nombre d'octets disponibles non validés (octets qui sont libres mais peuvent être récupérés par annulation) dans la page.

  • ibMicFree   Valeur indiquant le décalage de page pour l'octet disponible suivant en haut de la page.

Total de contrôle ECC

Le Total de contrôle ECC (Error Corrrecting Code) permet de corriger les erreurs mono bit dans les pages de base de données (dans le fichier .edb).

Il consiste en deux totaux de contrôle 32 bits. Le premier est un total de contrôle XOR où le numéro de page est utilisé comme valeur de départ dans le calcul. Le second est un total de contrôle ECC qui permet la correction des erreurs mono bit dans la page.

Incohérence de la base de données et erreurs -1018

Lors de la lecture d'une page, le moteur ESE analyse un indicateur figurant dans la page pour savoir si le total de contrôle de la page est au format actuel. Le total de contrôle approprié est ensuite calculé. S'il y a une incohérence dans des totaux de contrôle au format actuel, le moteur ESE tente de corriger l'erreur. Si l'erreur ne peut pas être corrigée, Exchange signale une erreur -1018.

La banque d'informations Exchange peut être à l'origine de la génération d'une erreur -1018 si elle effectue l'une des opérations suivantes :

  • Elle construit une page dont le total de contrôle est erroné.

  • Elle construit une page correctement mais indique au système d'exploitation un emplacement erroné pour l'écriture de la page.

Si un administrateur système rencontre une erreur -1018 ou exécute des tests matériels de diagnostic sur le serveur et que ces tests ne signalent aucun problème, il peut en conclure qu'Exchange est responsable du problème puisque le matériel satisfait l'analyse initiale.

Dans de nombreux cas, des analyses approfondies menées par Microsoft ou des fournisseurs de matériels ont fait apparaître que les dégâts causés dans le fichier de base de données étaient en fait dus au matériel, au microprogramme ou aux pilotes de périphériques.

Des tests de diagnostics ordinaires peuvent ne pas détecter les défaillances transitoires pour plusieurs raisons. Les problèmes au niveau du microprogramme ou du pilote peuvent dépasser les compétences des programmes de diagnostic. Les tests de diagnostics peuvent ne pas être en mesure de simuler de manière satisfaisante de longues durées d'exécution ou des charges complexes. En outre, l'ajout du suivi par diagnostic ou de l'enregistrement de débogage peut suffisamment modifier le système pour que le problème ne réapparaisse plus.

La simplicité et la stabilité des mécanismes Exchange qui génèrent les totaux de contrôle et écrivent les pages dans le fichier de base de données autorisent à penser qu'une erreur -1018 est probablement imputable à autre chose qu'à Exchange. Les mécanismes de totaux de contrôle et de détection de page incorrecte sont simples et fiables et leurs fondements sont restés les mêmes depuis la sortie de la première version d'Exchange, abstraction faite de modifications mineures apportées pour tenir compte des changes de format des pages de base de données entre les versions.

Un total de contrôle est généré pour une page qui est sur le point d'être écrite sur disque, après que toutes les autres données, y compris le numéro de la page même, soient écrites dans la page. Après avoir ajouté le total de contrôle à la page, Exchange demande au système d'exploitation Microsoft Windows Server d'écrire la page Web sur disque à l'aide d'API Windows Server standard publiées.

Le total de contrôle peut être correctement généré pour la page mais cette dernière peut être écrite au mauvais emplacement sur le disque dur. Cette erreur peut être le fait d'une erreur mémoire transitoire, telle qu'une inversion de bits. Supposons par exemple qu'Exchange construise une nouvelle version de la page 70. La page en elle-même ne connaît pas d'erreur mais la copie du numéro de page que le contrôleur de disque ou le système d'exploitation utilise est modifiée de manière aléatoire. Ce problème peut se produire si la valeur 70 (1000110 en binaire) a été remplacée par 6 (000110 en binaire) par une cellule mémoire instable. Le total de contrôle de la page reste correct mais l'emplacement de la page dans la base de données est maintenant erroné. Exchange signale une erreur -1018 pour la page lorsqu'il détecte que le numéro de page logique ne correspond pas à l'emplacement physique de la page.

Un autre type d'erreur de numérotation de page (causé par Exchange) peut se produire si Exchange écrit le mauvais numéro de page dans la page même. Cependant, dans ce cas, une autre erreur que l'erreur -1018 est signalée. Si Exchange écrit la valeur 71 dans la page 70 puis effectue correctement le total de contrôle dans la page, cette dernière est inscrite à l'emplacement 71 et réussit les tests de numéro de page et de total de contrôle.

Souvent, une seule erreur -1018 rapportée dans une base de données Exchange ne provoque pas l'arrêt de la base de données ou ne produit pas d'autres symptômes que le signalement de l'erreur même. La page peut se trouver dans un dossier auquel il est plus rarement fait accès (par exemple, le dossier Éléments envoyés ou Éléments supprimés), ou bien encore dans une pièce jointe rarement ouverte, voire vide.

Bien qu'une seule erreur -1018 soit peu susceptible de provoquer des pertes de données importantes, ces erreurs n'en sont pas moins préoccupantes car elles sont la preuve que le système de stockage a échoué au moins une fois lors d'une opération de stockage ou de récupération de données. Si l'erreur -1018 est sans doute un problème transitoire qui ne se reproduira jamais, il est fort probable que cette erreur soit le signe avant-coureur d'un problème qui ira en s'aggravant. Même si la première erreur -1018 se situe sur une page vide de la base de données, vous n'avez aucun moyen de savoir quelle sera la prochaine page endommagée. Si une table globale critique est endommagée, la base de données peut ne pas démarrer et la réparation peut partiellement ou totalement échouer.

Une fois qu'une erreur -1018 a été enregistrée, vous pouvez vous attendre à une panne imminente ou à l'apparition de dégâts aléatoires supplémentaires sur la base de données et devez prendre des mesures préventives, jusqu'à ce que vous ayez identifié et supprimé l'origine du problème.

Équilibrage de l'arborescence de base de données

L'une des principales fonctions du moteur ESE consiste à maintenir en permanence l'équilibre de la base de données. Le processus d'équilibrage de l'arborescence a lieu lorsque toutes les pages sont divisées ou fusionnées. Comme vous pouvez le voir à la figure suivante, le nombre de nœuds au niveau de la racine de l'arborescence est toujours le même ainsi qu'au niveau de la feuille. Ainsi, l'arborescence est équilibrée.

Arborescence équilibrée

Arborescence équilibrée

Du point de vue du moteur ESE, une table de base de données est un ensemble d'arborescences B. Chaque table se compose d'une arborescence B qui contient les données, bien qu'il puisse y avoir plusieurs arborescences B d'index secondaires qui servent à obtenir des vues différentes des données. Si une colonne ou un champ d'une table prend de l'ampleur au point de ne plus pouvoir être stocké dans l'arborescence B, il est divisé et placé dans une arborescence B distincte, appelée arborescence de valeurs longues.

La définition de ces tables et les arborescences B qui leur sont associées est stockée dans une autre arborescence B appelée catalogue système. La perte de ce catalogue est un problème grave. C'est pourquoi, le moteur ESE conserve deux copies identiques de son arborescence B dans chaque base de données.

Division

Lorsqu'une page est sur le point d'être saturée, la moitié des données environ est placée sur une page secondaire et une clé supplémentaire est placée dans la page parente de la page secondaire. Ce processus n'a pas lieu si la page parente est également pleine. Dans ce cas, la page parente est divisée et un pointeur est ajouté à sa propre page parente. Pour finir, il peut s'avérer nécessaire de diviser chaque page de pointeur jusqu'au bloc racine. Si ce dernier doit être divisé, un niveau de pages supplémentaires est inséré dans l'arborescence. Pour parler de façon imagée, on peut dire que l'arborescence croît en hauteur.

Fusion

Lorsqu'une page est presque vide, elle est fusionnée avec une page adjacente, les pointeurs de la page parente sont mis à jour et si nécessaire cette page est également fusionnée. Pour finir, si chaque page de pointeur jusqu'au bloc racine est fusionnée, l'arborescence diminue dans le sens de la hauteur. Pour parvenir jusqu'à une feuille (aux données), le moteur ESE commence au nœud racine et suit les pointeurs de page jusqu'à ce qu'il atteigne le nœud de feuille voulu.

Fanout

La structure d'une arborescence B ESE se caractérise par un Fanout très élevé. En effet, le moteur ESE peut atteindre n'importe quelle donnée dans une table de 50 Go en moins de quatre lectures sur disque (trois pages de pointeurs et la page de données elle-même). Le moteur ESE stocke plus de 200 pointeurs de page par page de 4 Ko, ce qui lui permet d'utiliser des arborescences avec un nombre minimal de niveaux parent/enfant (également appelées arborescences peu profondes). Le moteur ESE stocke également une clé de l'arborescence actuelle qui lui permet d'effectuer des recherches rapides à l'intérieur de cette arborescence. Le diagramme ci-dessus représente une arborescence à trois niveaux parent/enfant ; une arborescence à quatre niveaux parent/enfant peut stocker de nombreux gigaoctets de données.

Index

Une arborescence B traditionnelle n'est indexée que d'une seule manière bien spécifique. Elle fait appel à une seule clé et les données doivent être récupérées à l'aide de cette clé. Par exemple, les enregistrements dans la table des messages sont indexés sur la base de l'identificateur unique d'un message, appelé identificateur MTS (Message Transfer Service). Cependant, l'utilisateur souhaite probablement voir les données de la table des messages classées sous un format plus convivial.

Les index et plus spécifiquement les index secondaires, sont utilisés pour récupérer les données. Chaque index secondaire est une autre arborescence B qui mappe la clé secondaire choisie vers la clé principale. Les arborescences B sont ainsi de petite taille si on les compare aux données qu'elles indexent.

Pour comprendre le fonctionnement d'un index secondaire, étudions ce que se passe lorsqu'un utilisateur change le mode de présentation des messages dans un dossier. Si vous changez l'affichage du contenu d'un dossier dans Outlook pour que les messages soient affichés par sujet et non par heure de réception, Outlook oblige la banque et le moteur ESE à créer un index secondaire sur votre table de dossiers de messages.

Si vous modifiez l'affichage sur un dossier volumineux pour la première fois, vous devrez attendre quelques instants avant que l'affichage reflète la modification demandée. En observant de près le serveur, vous pouvez remarquer un léger pic au niveau de l'activité du disque. Lorsque vous revenez à la vue initiale, la réponse est beaucoup plus rapide car l'index est déjà construit.

Les arborescences B d'index secondaire du service Banque d'informations de Microsoft Exchange ont une durée de vie de 8 jours. Si elles ne sont pas utilisées, le service les supprime en arrière-plan.

Valeurs longues

Une colonne ou un enregistrement dans le moteur ESE ne peut pas s'étendre sur plusieurs pages dans l'arborescence B de données. Certaines valeurs (telles que PR_BODY, qui correspond au corps d'un message) dépassent la limite de 4 Ko allouée par page. Ces valeurs sont appelées valeurs longues et sont stockées dans une arborescence B de valeurs longues.

Si une donnée entrée dans une table ESE est trop volumineuse pour tenir dans une arborescence B de données, elle est divisée en pages de 4 Ko et stockée à part dans l'arborescence B de valeurs longues de la table. L'enregistrement dans l'arborescence B de données contient un pointeur vers la valeur longue. Ce pointeur est appelé identificateur LID (long value ID) et signifie que l'enregistrement comporte un pointeur vers le LID 256.

Format d'enregistrement

Un ensemble d'arborescences B représente une table et une table est un ensemble de lignes. Une ligne est également appelée un enregistrement. Un enregistrement se compose de nombreuses colonnes. La taille maximale d'un enregistrement, et par conséquent le nombre de colonnes pouvant apparaître au sein d'un seul enregistrement, est égale à la taille de page de la base de données, moins la taille de l'en-tête. Étant donné que la base de données autorise des pages de 4 Ko maximum, la taille d'enregistrement maximale est approximativement de 4,050 octets (4,096 octets moins la taille de l'en-tête de page).

Types de données de colonne

Chaque définition de colonne doit spécifier le type de données stockées dans la colonne. Le moteur ESE prend en charge les types de données décrits dans le tableau suivant.

Types de données de colonne du moteur ESE

Types de données de colonne Description

Bit

NULL, 0 ou non 0

Unsigned Byte

Entier non signé sur 1 octet

Short

Entier signé sur 2 octets

Unsigned Short

Entier non signé sur 2 octets

Long

Entier signé sur 4 octets

Unsigned Long

Entier non signé sur 4 octets

LongLong

Entier signé sur 8 octets

Currency

Entier signé sur 8 octets

IEEE Single

Valeur à virgule flottante sur 4 octets

IEEE Double

Valeur à virgule flottante sur 8 octets

Date Time

Date-heure sur 8 octets (date entière, heure fractionnaire)

GUID

Identifiant unique sur 16 octets

Binary

Chaîne binaire, longueur <= 255

Text

Chaîne ANSI ou Unicode, longueur <= 255 octets

Long Binary

Chaîne binaire de valeur élevée, longueur < 2 Go

Long Text

Chaîne ANSI ou Unicode de valeur élevée, longueur < 2 Go

Il existe deux catégories de types de données de colonne. La première regroupe les colonnes fixes et variables. La seconde contient les colonnes avec indicateurs. Chaque colonne est définie comme une structure FIELD sur 16 octets, à laquelle s'ajoute la taille du nom de colonne.

Lorsqu'une table est créée dans une base de données ESE, elle est définie par le biais d'un tableau de structures FIELD. Ce tableau identifie chaque colonne de la table à l'aide d'une valeur d'index appelée ID de colonne, à l'instar d'un tableau ordinaire dont les membres sont références par ID, tel que tableau[0], tableau[1], etc. L'accès aux colonnes par ID est rapide tandis que la recherche par nom de colonne requiert une analyse linéaire à travers le tableau de structures FIELD.

Colonnes fixes et variables

Les colonnes fixes contiennent des données de longueur fixe. Chaque enregistrement occupe un espace défini, même si aucune valeur n'est définie. Les ID de type de données 1 à 10 peuvent être définis comme des colonnes fixes. Chaque table peut définir jusqu'à 126 colonnes fixes (ID de colonne 1 à 127).

Les colonnes variables peuvent contenir jusqu'à 256 octets de données. Un tableau de décalage est stocké dans l'enregistrement comportant l'ensemble de colonnes variables le plus élevé. Chaque colonne nécessite deux octets. Les ID de type de données 10 et 11 peuvent être définis comme des colonnes variables. Chaque table peut définir jusqu'à 127 colonnes variables (ID de colonne 128 à 256).

Colonnes avec indicateurs

Le moteur ESE définit comme colonnes avec indicateurs des colonnes peu fréquentes ou dont il existe plusieurs occurrences au sein d'un seul enregistrement. Une colonne avec indicateur non définie n'occasionne pas de traitement supplémentaire sur le plan de l'espace. Il peut exister plusieurs occurrences d'une colonne avec indicateurs au sein d'un même enregistrement. Si une colonne avec indicateurs est représentée dans un index secondaire, chaque occurrence de cette colonne est référencée par l'index.

Les colonnes avec indicateurs peuvent contenir des données de longueur variable, illimitée. L'ID et la longueur de la colonne sont stockés avec les données. Tous les types de données peuvent être définis comme des colonnes avec indicateurs. Chaque table peut définir jusqu'à 64 993 colonnes avec indicateurs.