Share via


Architettura Extensible Storage Engine

 

Si applica a: Exchange Server 2007 SP3, Exchange Server 2007 SP2, Exchange Server 2007 SP1, Exchange Server 2007

Ultima modifica dell'argomento: 2008-11-19

I database delle cassette postali di Exchange e la coda nei server Trasporto Hub e Trasporto Edge utilizzano il database ESE (Extensible Storage Engine). ESE è un gestore di tabelle ISAM (Indexed Sequential Access Method, metodo di accesso sequenziale indicizzato) multiutente con funzionalità DML (Data Manipulation Language) e DDL (Data Definition Language) complete. Il motore ESE consente alle applicazioni di archiviare i record e creare indici per l'accesso ai record n vari modi.

Sono disponibili due versioni di ESE:

  • ESENTl   Il modulo di database per le componenti Active Directory e varie componenti Microsoft Windows. A differenza delle altre versioni di ESE (che utilizzano file di registro da 5 MB e pagine da 4 KB), l'implementazione di ESENT in Active Directory utilizza file di registro da 10 MB e pagine da 8 KB.

  • ESE98   Il modulo di database nei server Exchange Server 2000, Exchange Server 2003 e Exchange Server 2007.

  • ESE era precedentemente noto come JET (Joint Engine Technology) Blue. JET Blue non corrisponde alla versione di JET presente in Microsoft Access (nota come "JET Red").

Transazioni

ESE è un sofisticato modulo di database basato sulle transazioni. Una transazione è una serie di operazioni trattate come un'unità atomica (inscindibile). Tutte le operazioni di una transazione possono essere completate e salvate definitivamente oppure è possibile non eseguire alcuna operazione. Si considerino, per esempio, le operazioni interessate nello spostamento di un messaggio dalla cartella Posta in arrivo alla cartella Posta eliminata. Il messaggio viene cancellato da una cartella, aggiunto in un altra cartella e le proprietà della cartella vengono aggiornate. Se si verifica un errore, non si desiderano due copie del messaggio, non si desidera alcuna copia o in caso valori di proprietà della cartella (come Conteggio elementi) non coerenti con i contenuti effettivi della cartella.

Per evitare problemi di questo tipo, ESE riunisce le operazioni in una transazione. ESE garantisce che nessuna delle operazioni venga applicata definitivamente fino a quando la transazione non viene salvata nel file del database. Una volta salvata la transazione nel file del database, tutte le operazioni vengono applicate definitivamente.

Se un server smette di rispondere, ESE gestisce automaticamente anche il ripristino automatico al riavvio del server e annulla le eventuali transazioni non salvate. Se ESE fallisce prima del salvataggio di una transazione, l'intera transazione viene annullata ed è come se la transazione non fosse mai avvenuta. Se ESE smette di rispondere dopo il salvataggio di una transazione, l'intera transazione viene conservata e le modifiche sono visibili ai client.

Transazioni ACID

Le transazioni come quelle elencate nella sezione precedente si indicano in genere come transazioni ACID . ACID è l'acronimo dei seguenti attributi:

  • Atomic   Questo termine, atomico, indica che la modifica dello stato di una transazione è totale o non sussiste affatto. Le modifiche atomiche dello stato comprendono le modifiche del database, nonché i messaggi e le azioni a livello dei trasduttori.

  • Consistent   Questo termine, coerente, indica che una transazione costituisce la trasformazione corretta dello stato. Le azioni intraprese come gruppo, non violano alcun vincolo di integrità associato allo stato. È pertanto necessario che la transazione sia un programma corretto.

  • **Isolated **  Questo termine, isolato, indica che nonostante le transazioni vengano eseguite contemporaneamente, ogni transazione (t) rileva che le altre transazioni vengono eseguite prima di t o dopo t, ma non insieme.

  • Durable   Duraturo, le transazioni salvate vengono conservate nel database, anche se il sistema non risponde.

L'Archivio versione

L'Archivio versione consente a ESE di tenere traccia delle transazioni in corso e di gestirle. Per questa ragione, ESE può inoltrare parti isolate e coerenti del test ACID. L'Archivio versione prevede un elenco interno alla memoria di tutte le modifiche apportate al database.

L'Archivio versione si utilizza nelle seguenti situazioni:

  • Rollback   Se è necessario effettuare il rollback di una transazione, esamina l'Archivio versione per ottenere l'elenco delle operazioni effettuate. Effettuando al contrario tutte le operazioni, è possibile effettuare il rollback della transazione.

  • Rilevamento conflitto di scrittura   Se due diverse sessioni tentano di modificare lo stesso record, l'Archivio versione notifica e rifiuta la seconda modifica.

  • Letture ripetibili   Quando una sessione inizia una transazione, incontra sempre la stessa visualizzazione del database, anche se altre sessioni modificano i record visualizzati. Quando una sessione legge un record, l'Archivio versione viene consultato al fine di determinare quale versione del record debba essere visualizzata dalla sessione. Le letture ripetibili offrono un livello di isolamento in cui, dopo l'avvio di una transazione da parte di un client, viene visualizzato lo stato del database come era all'inizio della transazione, a prescindere dalle modifiche apportate da altri client o sessioni. Le letture ripetibili si implementano utilizzando l'Archivio versione. Grazie a un elenco interno alla memoria di tutte le modifiche apportate al database, è possibile determinare quale visualizzazione di un record debba essere visualizzata da una particolare sessione.

  • Registrazione anteimmagine differita   Questa è un'ottimizzazione di complesso che consente a ESE di registrare meno dati rispetto ad altri motori per database analoghi.

Isolamento snapshot

Dopo l'avvio di una transazione, ESE garantisce che la sessione visualizzi una sola immagine coerente del database, com'era all'inizio della relativa transazione, più le proprie modifiche. Anche altre sessioni possono modificare i dati e salvare le proprie transazioni, per cui tali modifiche non sono visibili alle transazioni iniziare prima del salvataggio. Un utente può modificare un record solo se sta visualizzando la versione più recente. In caso contrario, l'aggiornamento non riesce e si ha un JET_errWriteConflict. Le versioni precedenti l'ultima transazione vengono eliminate automaticamente.

ESE integra un livello di isolamento della transazione denominato Isolamento snapshot. Il livello Isolamento snapshot consente agli utenti di accedere all'ultima riga salvata, utilizzando una visualizzazione coerente con il database in termine di transizione. L'Isolamento snapshot è un algoritmo di controllo della concorrenza descritto in particolare nel documento Critica dei livelli di isolamento SQL ANSI (informazioni in lingua inglese). L'Isolamento snapshot viene implementato da ESE mediante letture ripetibili.

Struttura del database ESE

Tutti i dati all'interno del file di database in formato RTF sono archiviati in alberi B+. La "B" di albero B+ significa "bilanciato". "Albero" si riferisce a una disposizione simile a una struttura a cartelle in un sistema di file, dove la radice (root) rappresenta il contenitore principale degli elementi (pagine del database), che contengono a loro volta altri elementi. Gli alberi B+ sono stati ideati per offrire un accesso rapido ai dati su disco. Poiché la lettura e la scrittura su disco è molto più lenta rispetto all'esecuzione di queste operazioni in memoria, un albero B+ si divide in pagine da 8 KB. In questo modo, l'ESE può ottenere i dati necessari utilizzando un numero minimo di I/O su disco. Un database ESE può contenere fino a 2^31 (2 alla trentunesima) pagine da 8 KB, raggiungendo una dimensione massima di circa 16 terabyte. In realtà, le dimensioni del database sono limitate solo in funzione della capacità dell'utente di effettuare il backup, il ripristino e altre operazioni di manutenzione sul database (come la deframmentazione e le riparazioni offline del database) in tempo utile.

Pagine del database

Le dimensioni della pagina in ESE viene definita dall'applicazione che la utilizza. Per esempio, ESE98 (Exchange 2000 Server e Exchange Server 2003) utilizza pagine da quattro KB, mentre ESENT (Active Directory) utilizza pagine da otto KB. Ognuna di queste pagine da quattor o da otto KB contiene puntatori verso altre pagine o verso dati correnti e salvati nell'albero B+. Il puntatore e le pagine di dati sono mescolati all'interno del file.

Per incrementare le prestazioni, laddove possibile, le pagine vengono memorizzate nella cache di una memoria tampone per quanto possibile. In questo modo si riduce l'esigenza di passare al disco. Ogni pagina inizia con un'intestazione di pagina da 40 byte, che comprende i seguenti valori:

  • pgnoThis   Questo valore indica il numero di pagina della pagina.

  • DbtimeDirtied   Questo valore indica il tempo Dbtime relativo all'ultima modifica della pagina.

  • pgnoPrev   Questo valore indica il numero della pagina della pagina adiacente a sinistra sulla foglia.

  • pgnoNext   Questo valore indica il numero della pagina della pagina adiacente a destra sulla foglia.

  • ObjidFDP   Questo valore indica l'ID di oggetto di una pagina particolare nel database, denominato FDP (Father of the Data Page), che indica l'albero B+ a cui appartiene la pagina. La pagina FDP si utilizza in fase di riparazione.

  • cbFree   Questo valore indica il numero di byte disponibili sulla pagina.

  • cbUncommittedFree   Questo valore indica il numero di byte non assegnati e disponibili (byte liberi ma disponibili per richieste in fase di rollback) sulla pagina.

  • ibMicFree   Questo valore indica l'offset della pagina per il byte disponibile successivo sulla parte superiore della pagina.

Checksum ECC

La checksum ECC (Error Correcting Code) consente di correggere gli errori a livello dei singoli bit nelle pagine del database (nel file .edb).

Consiste di 2 checksum da 32 bit. La prima è una checksum XOR, in cui il numero di pagine viene utilizzato come seeding nel calcolo. La seconda checksum a 32 bit è una checksum ECC, che consente la correzione degli errori a livello dei singoli bit nella pagina.

Coerenza del database e ed Errori 1018

Durante la lettura di una pagina, ESE esamina un flag sulla pagina, per sapere se la pagina abbia il formato di checksum corrente. Viene quindi eseguito il calcolo della checksum adeguata. In caso di incoerenza della checksum con il formato corrente della checksum, ESE tenta di correggere l'errore. Se non è possibile correggere automaticamente l'errore, Exchange indica un errore -1018.

L'archivio Exchange può essere responsabile della generazione propria di un errore -1018 se si comporta come segue:

  • costruisce una pagina con un checksum non corretto;

  • costruisce una pagina correttamente, ma ordina al sistema operativo di scrivere la pagina in una posizione non corretta.

Se un amministratore di sistema incontra un errore -1018 o esegue test di diagnostica hardware sul server senza rilevare problemi, l'amministratore può dedurre che Exchange sia responsabile del problema, in quanto l'hardware ha superato l'analisi iniziale.

È capitato spesso che determinate analisi aggiuntive eseguite da Microsoft o dai fornitori hardware abbiano rilevato piccoli problemi a livello dell'hardware, del firmware o dei driver delle periferiche, di fatto responsabili del danneggiamento del file del database.

I test diagnostici ordinari potrebbero non rilevare tutti gli errori temporanei e le cause possono essere molteplici. I problemi a livello del firmware o del software driver possono eludere le capacità dei programmi di diagnostica. I test diagnostici potrebbero non essere in grado di simulare adeguatamente i tempi di esecuzione prolungati o carichi complessi. L'aggiunta di monitoraggi diagnostici o di registrazione debug può peraltro modificare il sistema in misura sufficiente per evitare che il problema si ripresenti.

La semplicità e la stabilità dei meccanismi Exchange, che generano le checksum e scrivono le pagine nel file del database lasciano intuire che un eventuale errore -1018 possa essere causato da qualcosa di esterno a Exchange. La checksum e i meccanismi di rilevamento di pagina non corretta sono semplici e affidabili, inoltre sono rimasti fondamentalmente invariati rispetto alla prima edizione di Exchange, salvo modifiche minori volte all'adeguamento alle modifiche di formato di pagina del database fra diverse versioni di database.

Una checksum viene generata per una pagina che sta per essere scritta su disco, dopo che tutti gli altri dati sono stati scritti sulla pagina, compreso il numero della pagina stesso. Dopo avere aggiunto la checksum alla pagina, Exchange ordina al sistema operativo del server Microsoft Windows si scrivere la pagina su disco utilizzando API di server Windows standard e pubblicate.

La checksum potrebbe essere generata correttamente per una pagina, ma la pagina potrebbe essere scritta in una posizione non corretta sul disco. Questo problema potrebbe dipendere da un errore temporaneo di memoria, come per esempio un "bit flip". Per esempio, supponiamo che Exchange realizzi una nuova versione di pagina 70. La pagina non presenta errori di per sè, ma la copia del numero della pagina utilizzato da controller del disco o dal sistema operativo varia in maniera casuale. Questo problema può verificarsi se 70 (binario 1000110) è stato modificato in 6 (binario 000110) da una cella instabile della memoria. La checksum della pagina è ancora corretta, ma la posizione della pagina nel database è momentaneamente scorretta. Exchange riporta un errore -1018 per la pagina quando rileva che il numero di pagina logico non corrisponde alla posizione fisica della pagina.

Un altro tipo di errore di numerazione (causato da Exchange) può verificarsi se Exchange scrive un numero di pagina non corretto sulla pagina stessa. Ma in tal caso, si hanno errori diversi, non il -1018. Se Exchange scrive 71 a pagina 70 ed esegue in seguito la checksum sulla pagina correttamente, la pagina viene scritta nella posizione 71 e supera sia il test del numero di pagina sia il test della checksum.

Spesso, un singolo errore -1018 riportato in un database Exchange non provoca l'interruzione del database né causa altri sintomi oltre alla presenza dell'errore -1018 stesso. La pagina potrebbe trovarsi in una cartella alla quale non si accede spesso (per esempio, le cartelle Posta inviata o Posta eliminata), oppure in un allegato aperto raramente o addirittura vuoto.

Nonostante sia improbabile che un singolo errore -1018 possa causare perdite di dati consistenti, gli errori -1018 sono motivo di preoccupazione, in quanto un errore -1018 è la prova che il sistema di archiviazione non ha archiviato o recuperato i dati in maniera affidabili almeno una volta. Nonostante l'errore -1018 possa essere un problema temporaneo che non si ripresenterà mai, è possibile che questo errore sia un segnale precoce si un problema che potrebbe progressivamente peggiorare. Anche se il primo errore 1018 interessa una pagina vuota nel database, non si può sapere quale sarà la prossima pagina danneggiata. Se viene danneggiata una tabella globale importante, il database potrebbe non avviarsi e la riparazione del database potrebbe non riuscire in parte o completamente.

Nel momento in cui viene registrato un errore -1018, è necessario tenere presente e considerare la possibilità di un problema imminente o ulteriori danni casuali al database, fino a quando la causa principale non sarà individuata ed eliminata.

Bilanciamento dell'albero del database

Una delle funzioni primarie di ESE è mantenere sempre bilanciato l'albero del database. Il processo di bilanciamento dell'albero si conclude nel momento in cui tutte le pagine sono state divise o unite. Come si vede nella figura seguente, il numero di nodi è sempre lo stesso sia alle radici sia alle foglie dell'albero. Per questo l'albero è bilanciato.

Albero bilanciato

Struttura bilanciata

Dal punto di vista del modulo ESE, una tabella di database è una raccolta di alberi B+. Ogni tabella consiste di un albero B+ che contiene i dati, nonostante possano essere presenti molti alberi secondari B+ di indici, utilizzati per offrire diverse visualizzazioni dei dati. Se una colonna o un campo in una tabella diventano troppo pesanti per essere archiviati nell'albero B+, essi vengono suddivisi in un albero B+ separato, detto albero long-value.

Le definizioni di queste tabelle e degli alberi B+ associati vengono archiviate in un albero B+ detto catalogo di sistema. La perdita del catalogo di sistema è un problema grave. In ESE vengono mantenute pertanto due copie identiche di questo albero B+ in ogni database.

Divisione

Se una pagina si riempie, circa la metà dei dati viene spostata in una pagina secondaria e viene posta una chiave n più nella pagina principale della pagina secondaria. Questo processo viene eseguito se non è piena anche la pagina principale. In tal caso, la pagina principale viene divisa e viene aggiunto un puntatore alla pagina principale in questione. Infine, ogni pagina del puntatore fino al blocco principale (root) potrebbe necessitare di essere diviso. Se il blocco principale necessita di essere diviso, viene inserito un ulteriore livello di pagine nell'albero. Figuratamente parlando, l'albero cresce in altezza.

Unione

Se una pagina è praticamente vuota, viene unita a una pagina adiacente, i puntatori della pagina principale vengono aggiornati e, se necessario, la pagina viene unita. Infine, ogni pagina del puntatore fino al blocco principale viene unito, per cui l'albero si riduce in altezza. Per raggiungere una foglia (dati), ESE inizia dal nodo principale e segue i puntatori della pagina fino a giungere al nodo della foglia desiderato.

Fan-Out

La struttura ad albero di un albero B+ ESE presenta un fan-out molto elevato. Fan -Out elevato significa che ESE può raggiungere qualsiasi dato un una tabella da 50 GB in appena quattro letture del disco (tre pagine di puntatori e la pagina dei dati stessa). ESE archivia oltre 200 puntatori di pagina per pagine da quattro KB, consentendo a ESE di utilizzare gli alberi con un numero minimo di livelli padre/figlio (detti anche alberi superficiali). ESE archivia inoltre una chiave relativa all'albero corrente, che consente a ESE di sfogliare rapidamente l'albero corrente. Il diagramma precedente è un albero con tre livelli padre/figlio; un albero con quattro livelli padre/figlio può archiviare molti gigabyte di dati.

Indici

Un albero B+ tradizionale può essere indicizzato in un solo modo, Utilizza una chiave e i dati devono essere recuperati utilizzando quella stessa chiave. Per esempio, i record nella tabella dei messaggi sono indicizzati in un identificatore unico del messaggio, detto ID del servizio di trasferimento del messaggio (MTS). Un utente potrebbe però desiderare di vedere i dati della tabella dei messaggi ordinati in un formato più agevole da consultare.

Gli indici, o più specificamente gli indici secondari, si utilizzano per recuperare i dati. Ciascun indice secondario rappresenta un altro albero B+ che mappa la chiave secondaria desiderata a quella primaria. In questo modo, gli alberi B+ risultano piccoli rispetto ai dati che essi indicizzano.

Per capire come viene utilizzato un indice secondario, si pensi a che cosa accade se un utente modifica il modo in cui i messaggi sono presentati in una cartella di messaggistica. Se si modifica la visualizzazione della cartella in Outlook, in modo che i messaggi siano ordinati per Oggetto anziché per Ricevuto, Outlook fa in modo che l'archivio e ESE creino un nuovo indice secondario nella tabella della cartella dei messaggi.

Quando si si modificano le visualizzazioni su una cartella di grandi dimensioni per la prima volta, si avrà un certo tempo di attesa. Guardando più da vicino il server, si vedrà un leggero picco nell'attività del disco. Quando si ripassa alla visualizzazione precedente, l'indice sarà già stato creato e la risposta sarà molto più rapida.

Gli alberi B+ secondari del servizio di archiviazione delle informazioni Microsoft Exchange permangono per otto giorni. Se non vengono utilizzati, il servizio di archiviazione delle informazioni Microsoft Exchange li cancella come operazione di background.

Long-Value

Le colonne o i record del database ESE non possono occupare più pagine nell'albero B+ dei dati. Vi sono valori (come PR_BODY, che è il corpo del messaggio di un messaggio), che superano il limite di 4 KB di una pagina. Questi valori sono detti Long-Value (LV). Un albero B+ di una tabella caratterizzato da long-value viene utilizzato per archiviare questi valori consistenti.

Se la dimensione dei dati inseriti in una tabella ESE è eccessiva e i dati non possono essere contenuti nell'albero B+ dei dati, questi vengono divisi in pagine di quattro KB e archiviati nell'albero B+ distinto per valori estesi della tabella. Il record nell'albero B+ contiene un puntatore al long-value. Questo puntatore è l'ID del long value (LID) e indica che un record ha un puntatore verso LID 256.

Formato del record

Una raccolta di alberi B+ forma una tabella, che a sua volta è composta da una raccolta di righe. Una riga può essere detta anche record. Un record consiste di più colonne. Le dimensioni massime di un record e pertanto il numero di colonne che compaiono in un singolo record dipendono dalle dimensioni della pagina di database meno le dimensioni dell'intestazione. ESE prevede pagine da quattro KB. Per questa ragione, le dimensioni massime del record corrispondono all'incirca a 4.050 byte (4.096 byte meno le dimensioni dell'intestazione)

Tipi di dati in colonna

Ogni definizione di colonna deve specificare il tipo di dati archiviato nella colonna. ESE supporta i tipi di dati descritti nella tabella seguente.

Tipi di dati in colonna Archiviazione estensibile

Tipi di dati in colonna Descrizione

Bit

NULLO, 0, o non-0

Byte non firmato

intero non firmato 1 byte

Breve

intero firmato 2 byte

Breve non firmato

intero non firmato 2 byte

Lungo

intero firmato 4 byte

Lungo non firmato

intero non firmato 4 byte

Lungo Lungo

intero firmato 8 byte

Diffusione

intero firmato 8 byte

Singolo IEEE

numero floating point a 4 byte

Doppio IEEE

numero floating point a 8 byte

Data Ora

data-ora a 8 byte (data intera, ora frazionaria)

GUID

identificatore unico a 16 byte

Binario

Stringa binaria, lunghezza <= 255

Testo

stringa ANSI o Unicode, lunghezza <= 255 byte

Binario lungo

Stringa binaria a valore consistente, lunghezza < 2 GB

Testo lungo

Stringa ANSI i Unicode a valore consistente, lunghezza < 2 GB

I tipi di dati in colonna si distinguono in due categorie. La prima categoria consiste nelle colonne fisse e variabili. La seconda categoria si riferisce alla colonne contrassegnate. Ogni colonna è una struttura FIELD a 16 byte, più le dimensioni del nome della colonna.

Quando si crea una tabella in un database ESE, la tabella si definisce utilizzando una matrice di strutture FIELD. Questa matrice identifica le colonne individuali nella tabella. Nel contesto di questa matrice, ogni colonna è rappresentata da un valore di indice, detto ID della colonna. È come una matrice ordinaria, in cui però è possibile referenziare gli elementi della matrice mediante un ID, come matrice [0], matrice [1], eccetera. L'accesso alle colonne con l'ID è rapido, ma una ricerca per nome di colonna richiede una scansione lineare attraverso la matrice delle strutture FIELD.

Colonne fisse e variabili

Le colonne fisse contengono una lunghezza di dati fissa. Ogni record occupa un volume di spazio definito per i record, anche se non è stato definito alcun valore. Gli ID dei tipi di dati da 1 a 10 possono essere definiti colonne fisse. Ogni tabella può definire fino a 126 colonne fisse (ID colonna da 1 a 127).

Le colonne variabili possono contenere fino a 256 byte di dati. Una matrice offset è archiviata nel record con l'impostazione di colonna variabile più elevata. Ogni colonna richiede due byte. Gli ID dei tipi di dati da 10 a 11 possono essere definiti colonne variabili. Ogni tabella può definire fino a 127 colonne variabili (ID colonna da 128 a 256).

Colonne contrassegnate

ESE definisce colonne che si presentano raramente o si presentano più volte in un singolo record come colonne contrassegnate. Una colonna contrassegnata non definita non incorre in sovraccarichi di spazio. Una colonna contrassegnata può presentarsi più volte nello stesso record. Se una colonna contrassegnata è rappresentata in un indice secondario, ogni singola occorrenza della colonna è referenziata dall'indice.

Le colonne contrassegnate contengono una lunghezza di dati illimitata e variabile. L'ID e la lunghezza della colonna sono archiviati insieme ai dati. Tutti i tipi di dati possono essere definiti come colonne contrassegnate. Ogni tabella può definire fino a 64.993 colonne contrassegnate.