I de två senaste inläggen diskuterade jag sätt att minska mängden transaktionsloggar som genereras och hur man säkerställer att transaktionsloggen alltid kan rensas ordentligt. I det här inlägget vill jag fortsätta med temat transaktionsloggprestanda och diskutera några transaktionsloggkonfigurationsproblem som kan orsaka problem.
För många VLFs
Transaktionsloggen är uppdelad i bitar som kallas virtuella loggfiler (VLF) så att logghanteringssystemet enkelt kan hålla reda på vilka delar av transaktionsloggen som är tillgängliga för återanvändning. Det finns en formel för hur många VLF du får när du skapar din transaktionslogg, odlar den manuellt eller så växer den automatiskt:
Upp till 1 MB | 2 VLF, var och en ungefär 1/2 av den totala storleken |
---|---|
1 MB till 64 MB | 4 VLF, var och en ungefär 1/4 av den totala storleken |
64 MB till 1 GB | 8 VLF, var och en ungefär 1/8 av den totala storleken |
Mer än 1 GB | 16 VLF, var och en ungefär 1/16 av den totala storleken |
Till exempel, om du skapar en transaktionslogg på 8 GB får du 16 VLFs där var och en är ungefär 512 MB. Om du sedan utökar loggen med ytterligare 4 GB kommer du att få ytterligare 16 VLF:er som vardera är ungefär 256 MB, för totalt 32 VLF:er.
Obs:den här algoritmen ändrades något för SQL Server 2014 för att lindra VLF-fragmenteringsproblemen – se det här blogginlägget för detaljer
En allmän bästa praxis är att ställa in loggens autotillväxt till något annat än standardvärdet 10 %, så att du kan kontrollera den paus som krävs när du nollinitierar nytt transaktionsloggutrymme. Låt oss säga att du skapar en 256 MB transaktionslogg och ställer in den automatiska tillväxten till 32 MB, och sedan växer loggen till en steady-state storlek på 16 GB. Givet formeln ovan kommer detta att resultera i att din transaktionslogg har mer än 2 000 VLF.
Så här många VLF kommer sannolikt att resultera i vissa prestandaproblem för operationer som bearbetar transaktionsloggen (t.ex. kraschåterställning, loggrensning, loggsäkerhetskopiering, transaktionsreplikering, databasåterställning). Denna situation kallas att ha VLF-fragmentering. I allmänhet kommer vilket antal VLF:er som helst att vara mer än tusen eller så att vara problematiska och måste åtgärdas (det mesta jag någonsin hört talas om är 1,54 miljoner VLF:er i en transaktionslogg som var mer än 1 TB stor!).
Sättet att se hur många VLF du har är att använda den odokumenterade (och helt säkra) DBCC LOGINFO
kommando. Antalet rader med utdata är antalet VLF:er i din transaktionslogg. Om du tror att du har för många är sättet att minska dem:
- Tillåt loggen att rensa
- Förminska loggen manuellt
- Upprepa steg 1 och 2 tills loggen når en liten storlek (vilket kan vara knepigt i ett upptaget produktionssystem)
- Utöka loggen manuellt till den storlek den ska ha, i steg på upp till 8 GB så att varje VLF inte är större än cirka 0,5 GB
Du kan läsa mer om VLF-fragmenteringsproblem och processen för att åtgärda dem på:
- Microsoft KB-artikel som rekommenderar att du minskar VLF-tal
- Kan tillväxten av loggfiler påverka DML?
- 8 steg för bättre transaktionslogggenomströmning
Tempdb
Tempdb måste ha sin transaktionslogg konfigurerad precis som vilken annan databas som helst, och den kan växa precis som vilken annan databas som helst. Men den har också en del lömskt beteende som kan orsaka problem.
När en SQL Server-instans startar om av någon anledning, kommer tempdbs data och loggfiler att återgå till den storlek de senast var inställda på. Detta skiljer sig från alla andra databaser, som förblir i sin nuvarande storlek efter en omstart av instansen.
Det här beteendet innebär att om tempdb-transaktionsloggen har vuxit för att klara den normala arbetsbelastningen måste du utföra en ALTER DATABASE
för att ställa in loggfilens storlek annars kommer dess storlek att minska efter en omstart av instansen och den måste växa igen. Varje gång en loggfil växer eller automatiskt växer måste det nya utrymmet nollinitieras och loggningsaktiviteten pausas medan det görs. Så om du inte hanterar storleken på din tempdb-loggfil korrekt, kommer du att betala en prestationsstraff när den växer efter varje omstart av instansen.
Vanlig loggfil krymper
Ganska ofta hör jag folk säga hur de vanligtvis krymper en databas transaktionslogg efter att den växer från en vanlig operation (t.ex. en veckodataimport). Det här är inte bra att göra.
Precis som jag förklarade ovan, när transaktionsloggen växer eller automatiskt växer, finns det en paus medan den nya delen av loggfilen nollinitieras. Om du regelbundet krymper transaktionsloggen för att den växer till storlek X, betyder det att du regelbundet lider av prestandaproblem eftersom transaktionsloggen automatiskt växer tillbaka till storlek X igen.
Om din transaktionslogg fortsätter att växa till storlek X, låt den vara! Ställ in den proaktivt till storlek X, hantera dina VLFs som jag förklarade ovan, och acceptera storlek X som den storlek som krävs för din normala arbetsbelastning. En större transaktionslogg är inget problem.
Flera loggfiler
Det finns ingen prestandavinst från att skapa flera loggfiler för en databas. Det kan dock vara nödvändigt att lägga till en andra loggfil om den befintliga loggfilen får ont om utrymme och du inte är villig att tvinga transaktionsloggen att rensa genom att byta till den enkla återställningsmodellen och utföra en kontrollpunkt (eftersom detta bryter loggbackupen kedja).
Jag får ofta frågan om det finns någon tvingande anledning att ta bort den andra loggfilen eller om det är ok att lämna den på plats. Svaret är att du bör ta bort det så snart du kan.
Även om den andra loggfilen inte orsakar prestandaproblem för din arbetsbelastning, påverkar den katastrofåterställning. Om din databas förstörs av någon anledning måste du återställa den från början. Den första fasen i en återställningssekvens är att skapa data och loggfiler om de inte finns.
Du kan göra datafilskapandet nästan omedelbart genom att aktivera omedelbar filinitiering som hoppar över nollinitieringen men det gäller inte loggfiler. Detta innebär att återställningen måste skapa alla loggfiler som fanns när den fullständiga säkerhetskopian togs (eller skapas under den tidsperiod som täcks av en transaktionsloggsäkerhetskopiering) och nollinitiera dem. Om du skapade en andra loggfil och glömde att släppa den igen, kommer nollinitiering av den under en katastrofåterställning att lägga till den totala driftstoppen. Detta är inte ett problem med arbetsbelastningsprestanda, men det påverkar tillgängligheten för servern som helhet.
Återgå från en ögonblicksbild av databas
Det sista problemet på min lista är faktiskt en bugg i SQL Server. Om du använder en databasögonblicksbild som ett sätt att snabbt återställa tillbaka till en känd tidpunkt utan att behöva återställa säkerhetskopior (så kallat återställning från ögonblicksbilden) så kan du spara mycket tid. Det finns dock en stor nackdel.
När databasen återgår från databasens ögonblicksbild, återskapas transaktionsloggen med två 0,25 MB VLF:er. Detta innebär att du måste utöka din transaktionslogg tillbaka till dess optimala storlek och antal VLF:er (eller så kommer den att växa automatiskt), med alla nollinitierings- och arbetsbelastningspauser som jag har diskuterat tidigare. Uppenbarligen inte det önskade beteendet.
Sammanfattning
Som du kan se av det här inlägget och mina tidigare två inlägg, finns det många saker som kan leda till dålig transaktionsloggprestanda, vilket sedan har en avsmittande effekt på prestandan för din totala arbetsbelastning.
Om du kan ta hand om alla dessa saker kommer du att ha sunda transaktionsloggar. Men det slutar inte där eftersom du måste se till att du övervakar dina transaktionsloggar så att du blir varnad för saker som automatisk tillväxt och överdriven läs- och skriv-I/O-fördröjning. Jag kommer att ta upp hur man gör det i ett framtida inlägg.