29.12.2012

Exchange ESE, osa 3


TRANSAKTIO


Johdanto
Ensinmäisessä artikkelissa on mainittu keskeiset lähteet ESE:en liittyen. Varsinaiset artikkelit ovat hyvin niukkasanaisia, mutta mainitut kaksi esitystä selvittävät jonkin verran asiaa syvemmältä. Tosin allekirjoittaneelle niistä herää lähinnä lisää kysymyksiä.

Transaktio
Transaktio on yksinkertaisuudessa toimenpide tai sarja toimenpiteitä (transactions), joilla muokataan fyysistä tietokantaa ts. tehdään muutoksia tietokantasivuihin (page). Tärkeimpiä toimenpiteitä ovat:

  • Insert - Lisätään tauluun uusi tieto esim. viesti.
  • Replace - Päivitetään olemassa oleva tieto esim. kansion viestien määrä.
  • Delete - Poistetaan olemassa oleva tieto esim. viesti.

Toimenpiteet, muutokset eli transaktiot kirjoitetaan ensin lokiin, jonka jälkeen muutokset kirjoitetaan muistista levylle, tietokantaan. Tätä kutsutaan myös nimellä Write ahead logging. Jokainen transaktio toteuttaa ns. ACID-mallia:

  • Atomic (all or nothing) – Joko kaikki toimenpiteet toteutuvat tai jonkun puuttuessa, mikään yksittäinen toimenpide ei toteudu.
  • Consistent – Tietokanta muuttuu eheästä tilasta toiseen eheään tilaan.
  • Isolated – Muutokset eivät ole näkyviä, kunnes toimenpiteet ovat onnistuneesti suoritettu. Jokainen transaktio suoritetaan aina eri aikaan, vaikka niitä näyttäisi olevan useita yhtä aikaan. Näin ollen yksittäinen transaktio (t) suoritetaan aina joko ennen (t) tai jälkeen toisen transaktion (t).
  • Durable – Onnistuneet toimenpiteet tulee pysyä tietokannassa järjestelmän vikaantuessa.




Transaktion lähde
Transaktion lähde tai asiakas on aina Exchange-palvelin ja tarkemmin ottaen Information Store-palvelu. Outlook-asiakasohjelma tekee kutsun MAPI RPC:n kautta Store-palvelulle, joka muodostaa kutsusta transaktion ja välittää sen ESE-komponentille. Itse tietokanta ei ole tietoinen Outlook-asiakkaasta ja sen alkuperäisestä kutsusta. Transaktion lähteitä on muitakin kuin Outlook-ohjelman kutsut. Järjestelmän tausta- ja ylläpitotoimenpiteet luovat omia transaktioita. Perusperiaate on se, että kaikki toimenpiteet, jotka muokkaavat tietokantaa, ovat transaktioita.

Artikkeleissa ja esityksissä käytetään klassista esimerkkiä, jossa viesti siirretään kansiosta toiseen. Itse esimerkissä ei ole sinänsä vikaa, mutta siinä sekoittuvat fyysinen ja looginen rakenne helposti. Outlookista käsin tarkasteltuna operaatio on looginen eli viesti siirretään kansiosta toiseen. Tarkkaa tietoa ei ole siitä, missä vaiheessa toimenpide muuttuu fyysisen tietokannan ymmärtämään muotoon. Voi olla, että ESE.dll tekee muutoksen loogisesta fyysiseksi. Tietokannan fyysistä rakennetta esim. yksittäisen postilaatikon näkökulmasta (kts. edellinen artikkeli) tarkastellessa huomaa, että sekä viesteillä että kansioilla on omat B+-puunsa. Otan tähän yhteyteen pari taulukkoa loogiselta puolelta perusteiksi asiaan. Ensimmäisessä taulussa on tietoja postilaatikon kansioista. Jokaisella kansiolla on useita attribuutteja, joista yksi FolderId. Samoin viestit ovat yhdessä taulussa ja viestillä puolestaan on monia attribuutteja, mutta myös FolderId. Viestissä oleva FolderId kertoo, missä kansiossa viesti on tai pikemminkin minkä kansion alla viesti esitetään loogisesti olevan. Fyysisesti viesti sijaitsee edelleen samassa tietokantapuussa.

Folders
Messages
Väittämäni on, että transaktiossa viestiä ei siirretä kansioista toiseen (eli kohteessa Insert-toimenpide ja lähteessä vastaavasti Delete). Tämä ”siirtäminen” liittyy nimenomaan asiakasohjelman käyttöliittymän muodostamaan kuvaan asiasta. Outlook esittää kansiot ja viestit hierarkkisesti, mutta jopa tietokannan loogisella tasolla ne eivät ole hierarkkisesti. Eli kun viesti siirretään kansioista toiseen, tosiasiallisesti loogisella tasolla viestin FolderId vaihtuu ja kansioiden viestien lukumäärä ja kokotiedot päivittyvät. Fyysisellä tasolla vastaavien sivujen muutokset tehdään Replace-toimenpiteellä. Tästä lisää pohdiskelua myöhemmässä vaiheessa.

Ross Smith väittää ESE Internals-esityksessään (kohta 15:05 ja 17:44), että jokainen kansio on oma taulunsa ja jokainen taulu oma B+-puunsa. En tiedä mitä tästä pitäisi todeta, koska Exchange 2003:ssa samassa tietokannassa olevien postilaatikoiden kansiot ovat yhdessä isossa taulussa (taulun nimi on yksinkertaisesti ”Folders”) ja Exchange 2010/2013 jokaisella laatikolla on yksi oma taulu (esim. ”Folders-1dd1-4208C2” ja ”Folder_105”) kansioita varten. Jokainen kansio (Inbox, Sent Items, jne.) eivät siis missään nimessä ole erillisiä tauluja. Vaikeaa on myös uskoa sitä, että Smith ei tietäisi tätä asiaa. Mene ja tiedä.

Muisti
Muistilla on tärkeä rooli transaktioissa. Muistissa on kolme tärkeää komponenttia: Log Buffer, ESE Cache ja Version Store. Näistä seuraavaksi tarkemmin.

Log Buffer
Log Buffer on välimuisti, jonka tehtävä on tallentaa ensin Exchange-palvelimelta tuleva transaktiopyyntö. Microsoft on antanut aiempiin Exchange versioihin (2003 ja vanhemmat) ohjeistuksia Log Buffer-muistin säätämiseen, mutta Exchange 2007 myötä on päädytty siihen, että Log Bufferin koko on sama kuin lokitiedoston koko eli 1024 KB. Tämä siitä syystä, että Log Buffer-arvon kasvattamisella ei ole havaittu merkittävää suorituskyvyn parantumista. Attribuutti on Active Directoryssa msExchESEParamLogBuffers ja se löytyy kohdasta:

CN=DB_name,CN=Databases,CN=Exchange Administrative Group (FYDIBOHF23SPDLT),CN=Administrative Groups,CN=ORG_name,CN=Microsoft Exchange,CN=Services,CN=Configuration,DC=Domain_Name,DC=Domain_Name

Jokaisella tietokannalla on oma Log Buffer-välimuistinsa ja tämä on ns. aktiivinen lokitiedosto tietokannan lokihakemistossa. Ensimmäisen tietokannan etuliite on E00 ja sen aktiiviloki on nimeltään E00.log.

Log Buffer on siis komponentti muistissa, jonka tehtävä on tallentaa kaikki meneillään olevat transaktiot omaan välimuistiin, jonka perusteella toimenpiteet voidaan kohdistaa itse tietokantaan.

ESE Cache
ESE Cachella on muitakin nimityksiä kuten IS Buffer tai IS Cache. ESE Cache on välimuisti, joka lataa ja poistaa muistista tietokantasivuja tietyn algoritmin mukaisesti. Algoritmia kutsutaan nimellä Least Recently Used Reference Count (LRU- K), joka pitää muistissa aktiivisessa käytössä olevia sivuja ja poistaa taas niitä, jos niitä ei ole käytetty vähään aikaan.

ESE Cache vaikuttaa olennaisesti levyn I/O-tarpeeseen. Vanhemmissa 32-bittisissä Exchange-versioissa ei ole ollut mahdollista määritellä kyseistä välimuistia kuin noin 900 MB, joka aiheuttaa sen, että tietokantasivuja ei pystytä pitämään muistissa kovinkaan paljon. Tästä taas seuraa, että tietokantasivuja pitää lukea usein levyltä, mikä on taas huomattavasti hitaampaa ja edellyttää suurta suorituskykyä levystöltä. Exchange 2007 ja uudemmat pystyvät käyttämään keskusmuistia niin paljon kuin tarvitaan. Replication Service-palvelulla on oma ESE Cachensa Log Replay-toiminnallisuutta varten.

Version Store
Version Store on komponentti muistissa, joka tallentaa alkuperäisen sivun välimustiin ennen siihen kohdistuvaa muutosta ja käyttää sitä seuraavasti:
  • Rollbacks – Palauttaa alkuperäisen sivun toimenpiteen epäonnistuessa.
  • Write conflict detection – Mikäli samaan tietueeseen kohdistuu useampi muutostoimenpide, jälkimmäinen hylätään.
  • Repeatable reads – Sivu pystytään lukemaan muiden asiakkaiden toimesta ennen kuin muutostoimenpiteet kirjoitetaan tietokantaan. Tästä käytetään myös nimitystä Snapshot Isolation, jonka tarkoitus on taata transaktion alkaessa kyseiselle istunnolle yksi, yhtenäinen ja eheä kuva tietokannasta sekä sen muutoksista. Samanaikaisesti on myös muita istuntoja, jotka muokkaavat tietokantasivuja. Nämä muutokset ovat kuitenkin näkymättömiä muille istunnoille ennen Commit-komennolla. Käyttäjä voi muokata tietuetta vain jos näkee viimeisimmän version sivuista, muuten järjestelmä palauttaa JET_errWriteConflict-virheen. Viimeistä transaktiota aiemmat sivujen versiot hylätään automaattisesti.
Version Storessa säilytetään sivuja vanhimpaan transaktioon asti, jota ei ole vielä kirjoitettu tietokantaan levylle.

Transaktion vaiheet
Exchangessa tapahtuvaa transaktiota kutsutaan myös nimellä Write ahead logging, jonka mukaan muutostoimenpiteet kirjoitetaan ensin lokiin ennen tietokantaan tallentamista.





Information Store ottaa vastaan transaktiopyynnön ja välittää sen ESE:lle. Transaktio alkaa Begin-komennolla (statement) ja sitä seuraa sarja operaatioita, jotka muokkaavat tietokannassa olevia sivuja.

Nämä operaatiot kirjoitetaan ensin (1) väliaikaiseen lokimuistiin, Log Buffer, jonka mukaan ESE Cachessa oleville sivuille tehdään muutos. Mikäli sivut eivät ole ESE Cache-muistissa, luetaan ne levyltä muistiin. Sivu muuttuu Dirty-tilaan (2) ja alkuperäisestä sivusta otetaan kopio Version Store-muistiin (3).

Jos ennen Commit-komentoa sovellus tai asiakasohjelma kaatuu tai tulee jokin muu häiriö, palautetaan Version Storesta alkuperäiset sivut, jolloin transaktio kumoutuu.

Kun Commit-komento on saapunut, välimuistiloki kirjoitetaan levylle olevaan lokitiedostoon (4), jonka jälkeen Log Buffer-välimuisti tyhjennetään (Log Flush) ja se on valmis seuraavia transaktioita varten. Log Flush tapahtuu myös silloin, kun Log Buffer tulee täyteen (1024 KB).




Checkpoint on piste, joka kertoo mitkä transaktiot on kirjoitettu onnistuneesti tietokantaan (5). Checkpointin koko (depth) määrittelee, kuinka paljon tietoa pidetään muistissa ennen levylle kirjoittamista. Exchange 2010 kirjoittaa sivuja levylle 30 sekunnin välein. Tieto päivitetään tietokannan chk-tiedostoon esim. E00.chk. Tämän jälkeen ESE Cache ja Version Store tyhjennetään kyseisten sivujen osalta (6).

Pohdintaa
Transaktiot tallennetaan ensin Log Bufferiin, jolloin samanaikaisesti ESE Cachessa oleva sivu muuttuu Dirty-tilaan. Esityksessä ei kerrota tarkemmin onko toimenpide tosiasiallisesti samanaikainen, jolloin esim. transaktiot kohdistuvat sekä Log Bufferiin että ESE Cacheen yhtä aikaa. Vai tallentuuko transaktio ensin Log Bufferiin, josta se luetaan ESE Cacheen? Tarkempaa tieto ei ole myöskään siitä, mikä mekanismi turvaa tiedon yhtenäisyyden Log Bufferin ja ESE Cachen välillä. Sivuja suojaa puolestaan tarkistussummat (ESE Cache ja Version Store). Log Buffer tyhjennetään (kirjoitetaan aktiiviseen Log-tiedostoon), kun se tulee täyteen tai kun Commit-komento päättää transaktiosarjan. Näin ollen Log Buffer voi tulla täyteen ennen kuin Commit-komento päättää transaktiosarjan, jolloin jos koko transaktio peruntuu, niin Log-tiedostoon on tallennettu kesken jäänyt transaktiosarja. Mikä on se prosessi, joka päättää, että transaktiota ei suoriteta ja Version Storesta palautetaan alkuperäinen sivu ESE Cacheen? Ja vielä, miten se tieto tallentuu Log-tiedostoon, että transaktio ei ole onnistunut kokonaisuudessaan vai tarvitaanko sitä tietoa Log-tiedostossa? Tietokanta on toki konsistentti, mutta jos Log-tiedostoa tarvitaan esim. palautustilanteessa, niin mikä vaikutus sillä on. Samalla logiikalla, jos Log-tiedostossa olevia transaktioita ajetaan tietokantaa vasten, niin kesken jääneet transaktiot jäävät kantaan kirjoittamatta.


Checkpoint File

Jokaisella transaktiolokiryhmälle (Log Stream) on oma Checkpoint-tietonsa. Kun tietokanta mountataan, tarkistetaan Checkpoint-tiedostosta, mihin asti transaktioita on onnistuneesti kirjoitettu ja mitkä ovat mahdollisesti vielä kirjoittamatta. Mikäli transaktiolokeja on vielä käsittelemättä esim. jonkin virhetilanteen takia, luetaan transaktiolokit tietokantaan. Tätä kutsutaan ns. Soft Recovery-palautumiseksi. Tietokannan Header-tiedot kertovat missä tilassa tietokanta on. Siinä kerrotaan myös, mitkä lokitiedot vaaditaan, että tietokannasta tulee eheä. Normaalissa tapauksessa lokien lukeminen ei kestä kauan ja tietokanta palautuu eheään tilaan. Checkpoint-tiedoston hävitessä, pitää tietokannan lukea kaikki transaktiolokit uudestaan tarkistaakseen, että transaktiot ovat kirjoitettu tietokantaan.

Log Filen sisältö
Lokitiedon sisältö on binäärimuotoinen ja sitä ei voi varsinaisesti avata millään editorilla katsottavaan muotoon, mutta se pitää sisällään kuvassa olevia asioita. Loki yksinkertaisuudessaan kirjaa kaikki tietokannan sivuun tehdyt muutokset. Jokainen transaktio alkaa Begin-komennolla ja loppuu aina Commit-komentoon. Mikäli Commit-komentoa ei tule, koko transaktio (muutos) perutaan.




Timestamp on aikaleima, joka ei perustu mihinkään varsinaiseen aikamuotoon (Date Format). Arvo on nouseva ja se on tietokantakohtainen. Aika muuttuu (incremental) joka kerta, kun tietokantaan kohdistetaan muutos. Hakasulkeissa oleva tieto kertoo, missä tieto sijaitsee tietokannassa. Ensimmäinen arvo kertoo tietokannan, toinen sivunumeron ja kolmas tietueen. Varsinainen tieto on MAPI Blob-muodossa.

Edellä oleva kuva on Ross Smith:n esityksestä ESE Essentials. Transaktion kuvauksessa on eräs looginen virhe, joka mietityttää ja josta olen maininnut jo yllä. Voiko transaktiolokissa olla tieto mihin tietueeseen (Record) muutos ollaan kohdistamassa ts. loogiseen rakenteeseen? Mielestäni ei. Tony Redmond käsittelee omissa Exchange-kirjoissaan myös lokitiedoston rakennetta ja niissä todetaan myös se sama, että binäärimuotoista tiedostoa ei voida varsinaisesti tarkastella millään editorilla, mutta rakenne voisi olla seuraavanlainen:




Kumpikin kuva on kuvitteellinen, mutta Redmondin kuva on mielestäni todenmukaisempi. Transaktiolokihan määrittelee fyysiseen tietokantaan tehdyt muutokset, jolloin tiedon sijainti (Offset) sivussa on hyvin olennainen asia. Tämä käy hyvin selväksi, kun sivun rakennetta tarkastelee (edellinen artikkeli).

Transaktiolokin voi avata vaikka Notepadilla. Siitä voi tunnistaa sieltä täältä selkokielistä tekstiä binäärimuodosta huolimatta.



Exchange 2010:n yhdessä transaktiolokissa näyttää olevan asennusloki selkokielisenä.



Lopuksi
Transaktio on todennäköisesti todellisuudessa monimutkaisempi prosessi, kuin artikkelit ja esitykset antavat ymmärtää. Ongelmaksi tässä tulee se, että jos on havaittavissa puutteita tai jopa virheitä nykyisissä materiaaleissa, niin miten on niiden tietojen laita, joita ei pysty mitenkään tarkistamaan. Miten ne pitävät paikkansa? Syntyy siis eräänlainen uskottavuusongelma. Toivottavaa olisi, että Microsoft päivittäisi materiaalinsa ajan tasalle. Kirjallinen materiaali kun on päivitetty viimeksi Exchange 2007:n aikoihin. Se voi olla, että artikkeleita ei päivitetä enää, koska Microsoftin painopiste on ilman muuta tarjota palveluitaan jatkossa pilvestä ja näiden teknisten tietojen hyödyntäminen on hyvin marginaalista.

Seuraavaksi tarkastellaan ESE:n loogista rakennetta.

Ei kommentteja:

Lähetä kommentti