Az utolsó sikeres DBCC

Előzőleg elmondtam ,hogy milyen fontos a DBCC CHECKDB futtatása, és erre gondolom mindenki kedvet kapott arra, hogy megnézze, mikor futott ez le az ő kis adatbázisain utoljára sikeresen. Felütötte mindenki a BOL-t, ééés… nem volt benne. Ja, ez is egyike azon undocumented apróságoknak:

DBCC DBINFO ('master') WITH TABLERESULTS;

Ez visszaad egy recordsetet, és abban select * where field = ‘dbi_dbccLastKnownGood’. Hát ennyi.

Mit tegyünk a korrupt adatbázisokkal?

Nemrégiben volt szerencsém felfrissíteni DR, vagyis disaster recovery (=füstölgő romokból hozz ki valamit) emlékeimet. Egy kb 50GB-os adatbázisunk összehalta magát. Már írt pár hibát a logba, hogy nem tud olvasni egy page-et, aztán emiatt a backupok sem sikerültek, úgyhogy jött a szerver restart. A szerver pedig aszonta, hogy az adatbázisunk suspect módba került. Ez azt jelenti, hogy nem lehet belépni se, megnézni se, semmise. Mit lehet tenni ilyenkor?

Az első tennivaló, hogy az összes létező tamtamot elkezdjük verni, és lepereg előttünk életünk filmje. Mert ha ez az egy adatbázis megsérült, megsérülhet más is – akár hardver, akár szoftver, akár csillagállás, igaz a többiekre is. Ha van mirror vagy log shipping secondary adatbázis, akkor aktiváljuk, ellenőrizzük, és nézzük meg, hogy ott vannak-e az adatok. Ha nem, akkor vakarjuk meg a fejünket, és olvassunk tovább.

Ezután igyunk egy kávét/kólát/ánizsteát, dohányosok szívjanak el egy cigit, és gondolkodjunk el azon, hogy hogy lehet a legjobban kimászni a helyzetből: itt jön a legutóbbi backupok kérdése,valamint a legutóbbi sikeres DBCC CHECKDB ideje, hogy lehetőleg ne állítsuk vissza mentésből a sérült adatbázist. A korrupt adatbázisra a hozzáértők egybehangzó tanácsa: állítsd vissza mentésből. És ez így igaz. Ez az egyetlen tuti módszer van, ha nincs egy működő tartalékod. Ha meg tudná csinálni tutibiztosan a SQL Server, megcsinálná magától, és nem lenne sérült az adatbázis.

Persze lehet, hogy a backup nem épp a legfrissebb (olyat nem írok, hogy nincs), és mégis kell valami adat a beteg db-ből. Ekkor nem ússzuk meg a hősi munkát. Az én általános DR tervem a következő:

  1. Ellenőrzöm, hogy van-e elég szabad helyem ahhoz, amit fogok csinálni: adatfájloknak, tranlognak (jó nagy lesz, amit a #2 csinál), backupnak.
  2. Elkezdem a restore-t, amilyen gyorsan csak tudom, egy új adatbázisba.
  3. A suspect adatbázist felhozom emergency módba (ALTER DATABASE Titanic SET EMERGENCY), és elkezdem kitolni belőle amit csak lehet: a teljes sémát megpróbálom kiscriptelni egy új adatbázisba (indexekkel, foreign keyekkel, default értékekkel, de legfőképpen identity oszlopokkal), aztán megpróbálom az adatokat is átpumpálni bele. Itt jön az izgalom: ha a db korrupt, akkor valahol valami nem fog sikerülni. Jó esetben hibát is dob a SQL. De nekünk itt pl. nem dobott hibát, csak csendben lenyelte az utolsó három napnyi adatot. Tehát mindenképpen kell a humán adatellenőrzés.
  4. Ha a #2 lement, rátolok egy DBCC CHECKDB WITH REPAIR_ALLOW_DATA_LOSS-t a db-re, hátha többet vissza tud utána adni, mint a #2-ben. Persze lehet, hogy kevesebbet.
  5. Ha megvan a működő adatbázisom valahogy a háromból, akkor leellenőrzöm logikailag az adatokat, tolok rá egy DBCC-t, egy backupot, beállítom a backup jobot hozzá, és ráengedem az alkalmazást.

Miért szivatom magamat mind a hárommal egyszerre? Mert a backup-restore jól hangzik, de ha kiderül, hogy baja van már a backupnak is, akkor az az elvesztett idő később fájni fog. Plusz ha nem csináltam az elmúlt pár percben tranlog backupot, akkor még adatot is veszítek tutira. Ha ki tudom szedni a legutolsó adatokat a sérült DB-ből, az lefedheti az így keletkezett hézagot. A #2 egy logikus lépés, a #3 szintén, és mint jeleztem, más adatokra számíthatunk. Pl. ha megsérült egy tábla közepén a clustered index, amit a repair ki tud vágni, akkor egy 10000 soros táblából #2 visszaadhatja az 1-2450 sorokat, #3 pedig az 1-2100 és 2900-10000 sorokat. Igen, hiányzik a közepe. Na és? Ha annyira fontos, akkor tessék mirrorozni.

Itt jegyzem meg, hogy szerintem az egyetlen tuti biztonságos tartalékképzési módszer a High Safety, azaz szinkron mirroring. Itt ugyanis nem a diszkről olvassa vissza az SQL Server, hogy mit is csinált az aktív adatbázis, hanem a memóriából kitolja mindkét helyre. Ez pl. egy esetlegesen felbukkanó hibánál sokat számít, például ha csak időnként ront el valamit a diszk kontroller, és ráadásul egy ideig még érvényes adat is marad a tranzakciós logba került szemét. Na nem mintha láttam volna már ilyet, csak úgy mondom. Cserébe a szinkorn mirroringnak van hatása a teljesítményre is, konkrétan csökkenti, mivel minden commit előtt van egy rövid megbeszélés a principal (aktív) és mirror (passzív) adatbázis szerverek között.

Végül hadd vonjam le a tanulságokat:

  • Legyenek backupjaid, ellenőizd, hogy készülnek-e, teszteld őket időnként.
  • Futtass rendszeresen DBCC CHECKDB-t. Ideális esetben legalább minden full backup előtt, így lényegesen nagyobb esélyed van arra, hogy a backupod jó lesz.
  • Legyen DR terved, és próbáld is ki, amennyire csak tudod.
  • Legyen tartalékod a fontosabb adatbázisaidból. Fantasztikus tud lenni 5 perc alatt megoldani egy DR-nek induló szituációt.

Korrupt adatbázisok – honnan szerezz egyet?

A tudásszomjas DBA életében az egyik legnehezebb dolog gyakorlatot szerezni a DBCC CHECKDB által dobott hibák megjavításában. Először is ritkán fordulnak elő, másodszor pedig nincs sok dobása az embernek, amikor előfordul. Játékból meg nehéz sérült adatbázist csinálni, pláne olyat, amiről tudja az ember fia, hogy pontosan mi baja is van.

Persze kis szakismerettel már neki lehet állni, és hexaeditorral belecsapni az adatfájlba, de akkor is maradhatnak homályos részek, pl. akkor most pontosan mit is rontottam el, indexet vagy adatot.

A kényelmes/lusta/mérnöki megoldás pedig az, hogy letöltöd a Paul Randal által nagy gonddal elrontott adatbázis-kollekciót. Ebben többféle, célra rontott adatbázis lakik, van olyan, amin már a CHECKDB sem fut le. SQL 2005-re lettek készítve, mint az Paul cikkéből kiderül…

Csináljunk Maintenance Plant az adatbázisainkhoz! Csináljunk?

Aki ott volt a Technet üzemeltetői konferencián vagy letöltötte az internetről valamely darabkáját az előadásomnak, az emlékezhet rá, hogy ajánlottam a maintenance planek használatát mentések készítéséhez. A maintenance planek SQL 2005-ben tulajdonképpen Integration Services csomagok, azok csinálják a mentést, DBCC CHECKDB-t, stb. A wizarddal pikk-pakk össze lehet rakni egyet, és már ülhetünk is nyugodtan a babérjainkon (azért ne felejtsük el beállítani, hogy a jobok elbukása esetén küldjön levelet).

Ez mind jól hangzik, de: én nem szeretem, ha az ember dolgozik a gép helyett, tehát az adatbázis létrehozást is automatizáltam – mivel sorban töltöm fel a szerveket, mindig van egy olyan, amelyikre az új adatbázisok kerülnek. Úgyhogy írtam egy scriptet, amelyik létrehozza a teszt és/vagy éles adatbázist, a hozzá tartozó userrel együtt, akinek beállít egy 20 karakteres random jelszót, és íme: a linuxos kollégáim meg tudják csinálni az új adatbázisokat, nem kell várniuk arra, hogy egy DBA megcsinálja, a DBA-nak meg nem kell izgulnia, hogy mit rontott el a sysadmin :) Ebből már csak egy dolog hiányzik: a karbantartás és a mentés. Úgyhogy nekiálltam automatikusan legyártani az Integration Services csomagokat. Hadd fogalmazzak finoman: az egyik legsötétebb zsákutca volt, ahol valaha jártam. Végül eljutottam oda, hogy valami irgalmatlan nagy gányolással meg lehet oldani, és még így is marad benne némi homály. És ez nekem betett.

Úgyhogy szemléletet váltottam: a Transact-SQL kiválóan alkalmas backupok készítésére, akár időbélyeggel is, és mióta feltalálták a powershellt, a régi backup fájlok törlése sem okoz gondot. A full backup előtt természetesen lefut egy DBCC CHECKDB, ez pont plusz egy sor a T-SQL scriptben, és örülhetek, hogy mindig jó mentést teszek el. Az összes egyé karbantartást is meg lehet oldani T-SQL-lel (sp_updatestats, index javítás/újraépítés), úgyhogy nagyon kicsit sajnálkozva, ugyanakkor örülve az automatizált környezetemnek jelentem: kidobtuk a maintenance planeket. Majd ha lehet egyszerűen generálni őket, visszanézek.

(ja, nemsokára felteszem a scripteket is :))

A detach és az NTFS jogosultság

Azért szeretek fórumot olvasni, mert mindig tanulok. Vagy vmi hasznosat, vagy azt, hogy nem ezt a fórumot kellene olvasni. Ma délután találkoztam a magyar Technet SQL fórumon egy érdekes kérdéssel:
Miért nem működik a következő script, miért dob a második lépés access denied-ot, mikor explorerből, Total Commanderből megy az átnevezés? Sőt, ha elmásolják és vissza, akkor utána már lehet xp_cmshellel is átnevezni.

exec sp_detach_db 'database'
exec xp_cmdshell 'rename d:\mssql\data\database.mdf database.old.mdf'

Azaz a detach sikerül, utána a cmdshell meg access denied-ot mond. Ez roppantul felkeltette a kíváncsiságomat, és pont volt egy kis időm is, úgyhogy ránéztem a dologra. Kipróbáltam a W2K3-SQL2K8 express asztali gépemen, és pont ezt tapasztaltam. Mivel az express tele van meglepetésekkel, megnéztem a 2K3-SQL2K5 virtuális gépemen is, és dettó. Ezután megnéztem a jogosultságokat az adatbázis fájlokon, ha már access denied a hiba, és azt láttam, hogy az attacsolt fájlokhoz a SQL service-t futtató csoportnak meg az Administrators csoportnak full control joga van, a detacsolt fájlokon meg csak az én saját, nem-adminisztrátor useremnek van full controlja. Ha attacsoltam, visszakerült a SQL service joga is. Szóval kiderült, hogy a DBCC DETACHDB, amit a sp_detach_database hív a lelke mélyén (meg lehet nézni a master adatbázisban a definícióját), kicsit trükkösen kezeli a jogokat. És mivel elvette a SQL userem jogát, az xp_cmdshell elég csúnyán megbukott, mert ugye alapból a SQL user nevében próbálkozik futtatni a parancsokat. Ha bármikor valakinek kételye volna, nagyon egyszerű kideríteni, hogy kinek a nevében futnak a parancsok:

exec xp_cmdshell 'echo %username%'

Ez pont ki fogja írni. Vissza is kaptam a SQL service accountom nevét. Continue reading ‘A detach és az NTFS jogosultság’ »