SQL 2005 SP3 install és elmozgatott rendszeradatbázisok

Épp eszembe jutott, és gondoltam megosztom mindenkivel: pár hónapja SP3-at installáltunk a SQL-re, és azt találtuk, hogy elfrakkol az install. Újrakezdve is elfrakkolt. Meg kellett nézni a logot (programkönyvtár\Setup Bootstrap könyvtárban laknak ezek az izék), és kiderült a hiba: a distmodel.mdf fájl hiányzott a drágámnak, mert ott kereste, ahol a master.mdf volt, de mi átmozgattuk máshova időközben. Úgyhogy baráti jótanács: ha elmozgatjátok a rendszeradatbázisokat, mozgassátok az összes adatfájlt együtt :) Kicsit deja vu érzésem van – lehet, hogy ezt már megírtam egyszer?

Command-line SQL… install vagy amit akartok

Hogy legyen valami kis SQL is a blogomon, megosztom veletek egyik aktuális kedvencemet. (Be kell valljam, hogy alapból nem értek jobban a SQL Serverhez egy átlag foltos tengerimalacnál, de mindig találok valami érdekeset benne, azt elolvasom, aztán akkor abból okos vagyok egy hétig vagy kettőig. De ezt ne mondjátok meg az MS-nek:) Mint visszatérő olvasóim tudják, élek-halok a parancssoros-begépelős-villogókurzoros üzemeltetésért, néha sehogysem értem, hogy hagytam ott a Linuxot fiatalkoromban (aztán mindig eszembe jut, hogy azért, mert X-et két nap alatt tudtam csinálni, hangot meg sohasem a RH7 alatt). És kérem, az SQL Serverben vannak dolgok, amik csak gépeléssel érhetőek el. SQL-t installállni lehet GUI-ból és CLI-ből is – na de editiont upgrade-elni, vagy automatikusan installálni csak parancssorból lehet. Mivel folyton 100 dolgot csinálok, nekem kényelmesebb egy cluster úgy installázni, hogy a fekete ablakba bepötyögöm (vagy copy-paste a BOL-ból):

Start /wait X:\servers\setup.exe /qn VS=<vsname> INSTALLVS=SQL_Engine INSTANCENAME=<instancename> ADDLOCAL=SQL_Engine,Client_Components PIDKEY=<pidkey value with no "-"> ADDNODE=<nodename1 ,NodeName2> GROUP=<diskgroup> IP=<ip ,Networkname> ADMINPASSWORD=<strongpassword> SAPWD=<strongpassord> INSTALLSQLDIR=<installationpath> INSTALLSQLDATADIR=<sharedrivepath> SQLACCOUNT=<domain \user> SQLPASSWORD=<domainuserpassword> AGTACCOUNT=<domain \user> AGTPASSWORD=<domainuserpassword> SQLBROWSERACCOUNT=<domain \user> SQLBROWSERPASSWORD=<domainuserpassword> SQLCLUSTERGROUP="MyDomain\MySQLDomainGroup" AGTCLUSTERGROUP="MyDomain\MyAGTDomainGroup" FTSCLUSTERGROUP="MyDomain\MyFTSDomainGroup" ERRORREPORTING=1, SQMREPORTING=1 SQLCOLLATION=SQL_Latin1_General_CP1_CI_AS

Aztán elmegyek ebédelni, és nem klikkelgetek húsz percet, mire eljutok az installhoz. De nem is ez a legjobb rész benne, hanem az, hogy a cluster install amúgy is szívás: install szerver+kliens az aktív node-ra, majd install kliens (+SSIS) a passzív node-(ok)ra. Minden hotfixnek is ugyanúgy le kell mennie az összes node-ra, mert a nem patchelt kliens cucc az egyik leggonoszabb veszélyforrás. Nem értjük, hogy miért nem működik, pedig jól összekattogtattuk. Ja, a kliens RTM, és rossz queryt futtat a háttérben…

Szóval a lényeg, hogy letolhatom az installt szinte-szinte automatában így scriptelve, megdöbbentően sok paramétert be lehet állítani, soha nem hittem volna, hogy ilyen agyrémek vannak, mint Management Studio shortcut rebuild meg effélék. Az edition upgrade viszont még nagyobb móka volt, konkrétan egy Evaluationt kellett Developerré növesztenem. Össze is raktam a cuki kis parancsot, bedobtam minden elvárt paramétert, aztán mindig elkezdett kérdezgetni, hogy akkir itt az interaktív rész, mondjam meg az instance nevét meg effélék. Némi gondolkodás után sem jöttem rá, hogy ezt most pebkac vagy anti-user-friendly megoldás: van két kapcsoló az installerhez: a /qb basic dialógus ablakokat és hibákat feldob, a /qn pedig semmit, még hibát se. Úgy hal meg, hogy a logba írja, miért tette. Na, én /qb-vel elindultam, és sorban megakadtam. Végül megpróbáltam /qn-nel, és tovább jutottam. Egész eddig:

SQL Server Setup has encountered the following problem: [Microsoft][SQL Native Client][SQL Server]The certificate cannot be dropped because one or more entities are either signed or encrypted using it.. To continue, correct the problem, and then run SQL Server Setup again.

At is mondta persze, hogy A certificate with the name ‘##MS_AgentSigningCertificate##’ already exists or it has already been added to this database. Néztem, mint Rozi a filmszínházban. Irány a gugli (vagy a bing, összevissza használom őket, általában pontosan az egyik keres kedvem szerint), és íme, a megoldás egy fórumban: le kell futtatni egy kis scriptet, és újra megpróbálni:

use msdb

BEGIN TRANSACTION

declare @sp sysname
declare @exec_str nvarchar(1024)
declare ms_crs_sps cursor global for select object_name(crypts.major_id) from sys.crypt_properties crypts, sys.certificates certs where crypts.thumbprint = certs.thumbprint and crypts.class = 1 and certs.name = '##MS_AgentSigningCertificate##'

open ms_crs_sps

fetch next from ms_crs_sps into @sp

while @@fetch_status = 0

begin
 if exists(select * from sys.objects where name = @sp)
 begin
  print 'Dropping signature from: ' + @sp set @exec_str =   N'drop signature from ' + quotename(@sp) + N' by certificate [##MS_AgentSigningCertificate##]'
  Execute(@exec_str)
  if (@@error <> 0)
  begin
   declare @err_str nvarchar(1024)
   set @err_str = 'Cannot drop signature from ' + quotename(@sp) + '. Terminating.'
   close ms_crs_sps
   deallocate ms_crs_sps
   ROLLBACK TRANSACTION
   RAISERROR(@err_str, 20, 127) WITH LOG
   return
  end
 end
fetch next from ms_crs_sps into @sp
end

close ms_crs_sps
deallocate ms_crs_sps
COMMIT TRANSACTION
go

A homlokomra csaptam: hogy ez hogy nem jutott eszembe magamtól! És ezután már le is futott az edition upgrade. Mndenféle emberi beavatkozás nélkül. Kocka…

SQL Server cluster security szigorítás how-not-to

Az SQL Server 2008 előtti változatai úgy installálódtak, hogy a lokális adminisztrátor csoport alapból be volt téve az SQL sysadmin role-ba. Időnként, főleg nagy cégeknél, ez nem kívánatos mellékhatásokkal jár, például olyan emberek és accountok kapnak automatikusan jogot az SQL-hez, akiknek semmi közük hozzá egyébként. Így történt, hogy egyszer régen, nagyon régen engem is utolért ez a feladat: válasszam le a Windows adminokat a SQL sysadminokról. Habár ez egy régi történet, többen azóta is emlegetik, úgy elcsesztem, úgyhogy a legutóbbi felhánytorgatáskor úgy döntöttem, megosztom a nagyérdeművel, tanuljatok az én hibámból.

Alapvetően egy éles rendszeren végzett változtatással álltam szemközt, úgyhogy a teszt SQL clusteren megcsináltam a változtatást, felírtam, hogy mit csináltam, és nekiálltam az éles rendszernek is. A feladat mindössze annyi volt, hogy a kivett BUILTIN\Administrators helyett be kellett raknom a DOMAIN\MyTeam csoportot sa-nak, és kész. Hogyan lehet ilyet letesztelni? Mivel clusterről beszélünk, én végigbillentem a SQL-t az összes node-ra, hogy lássam, hogy mindenhol el tud indulni rendesen az új beállításokkal, illetve tudok is hozzá kapcsolódni (ez utóbbira sqlcmd-t használok). Ha az OS-t piszkálom, akkor node reboot után megy ugyanez. Éles négy node-os cluster esetén ez kissé időigényes, és a fél perc helyett négy perc szolgáltatáskiesést okoz, de esküszöm, hogy megéri.

Szóval megcsináltam a változtatást az éles rendszeren is, megnéztem, minden működött, mindenki be tudott lépni, úgyhogy le is zártam az ügyet, és foglalkoztam a többi dologgal. Aztán egy pár hét múlva éjféltájban felhívott az ügyeletesünk, hogy a fent említett cluster nem indul el. Kérdeztem, hogy mi a tünet, és azt mondta, hogy felhívták azzal, hogy piros a monitor, megnézte, a cluster admin szerint el volt dőlve a szolgáltatás, megpróbálta újraindítani, el is indult minden egy időre, aztán egy-két perc után megint elfrakkolt, ezt eljátszotta párszor, azóta meg failed állapotban van. Rutinos üzemeltetőként végigpörgött a fejemben, hogy mi mindent csináltunk a szerverrel az elmúlt időben, és a tünetek alapján rögtön tudtam, hogy mi a baj. Azért megkértem ,hogy nézze meg az errorlogot, amire elmondta az azóta híressé vált mondatot: „valami júzer be akar jelentkezni itt, és nem sikerül neki – de ez most mindegy, amíg nem fut a cluster rendesen”.

Itt egy kicsit röhögtem, és elmondtam neki, hogy a valami júzer a cluster service-t futtató account, és úgy működik a dolog, hogy a cluster service elindítja a clusterezett resource-okat, így például az SQL Server service-t, és pollozza őket, hogy működnek-e. Az SQL Server pollozása pedig úgy néz ki, hogy belogol a cluster service account, és időnként egy select @@servername query-t bedob. Ha ez sikerül, örül, ha nem, akkor egy megadott idő (default 180 másodperc, ha jól rémlik így a vonaton) után betegnek nyilvánítja a SQL Server service-t, és megállítja. Kiderült, hogy egy korábbi bohóckodás miatt a teszt clusteren már hozzá volt adva a cluster service külön SQL accountként, úgyhogy ott nem is volt semmi hiba. Az élesen csak az ütött be, amikor leterhelték a clustert, és megállt a SQL, majd el akart megint indulni, addig ugyanis nem próbált meg belogolni újra a cluster service account, így nem zavarta, hogy dobtam (vagyis droptam) a loginját. Amikor újraindult a SQL, kiválóan működött minden – 180 másodpercig, amikor is a sok hiábavaló próbálkozás után a cluster service betegnek nyilvánította az egyébként makkegészséges szervert, és lelőtte. A baj az volt, hogy megfelelő számú próbálkozás után már el sem jutottunk odáig, hogy elinduljon a SQL és beléphessünk megjavítani. Úgyhogy jött mindenki barátja, a single user mód: sqlservr -c -m, amiben sqlcmd-vel belépve kiválóan meg lehetett pákázni. Ilyenkor persze a SQL tényleg a cluster node-on fut, nem virtual serverként, tehát nem úgy lehet hozzá csatlakozni, mint máskor, hanem (local) vagy . vagy hosztnév. Gyorsan csak ennyit mondtunk:

create login ’DOMAIN\_clusterserviceuser’ from windows

Figyelembe véve, hogy ő a szerver nevén kívül nem kérdez semmit, nagyon boldog a public role-lal, nem kell neki több jog. El is indult, örültünk is.

Tanulságok:

  • A teszt és éles rendszereket szinkronban kell tartani.
  • A változtatások után mindig meg kell győződni arról, hogy mindent életben hagytunk: újraindítani az érintett service-eket, stb.

SQL 2005 Failover Cluster és az el nem induló SQL Agent

Installáltam egy clustert, és a konfiguráció közben egyszer csak azt vettem észre, hogy az SQL Agent nem akar elindulni. Örömöm nem ismert határokat, elkezdtem túrni az agent logját (SQLAGENT.OUT, gyári alapbeállításként az errorloggal egy könyvtárban lakik), és megállapítottam, hogy igazából már az utolsó három restartnál nem indult el, csak én nem néztem a cluadminban, hogy mi milyen színű, és csak SSMS-t, sőt néha csak SQLCMD-t használtam (reprodukálható konfiguráció készítése volt a cél, ott meg a GUI nem játszik nagyon). Szóval megállapítottam, hogy SP3-mal még ment, SP3 CU4-gyel már nem, a kettő közt meg nemtom mikor tört el, a CU installjánál vagy később. Mindegy, emlékeztem még fiatalabb koromból, hogy olyan esetekben, amikor nem lehet a (local) szerverhez csatlakozni, valami registrykulcsba be kell tolni a szerver nevét, hogy ne így nézzen ki az SQLAGENT.OUT:

2008-01-10 20:57:15 - ! [298] SQLServer Error: 10061, TCP Provider: No connection could be made because the target machine actively refused it. [SQLSTATE 08001]
2008-01-10 20:57:15 - ! [165] ODBC Error: 0, Login timeout expired [SQLSTATE HYT00]
2008-01-10 20:57:15 - ! [298] SQLServer Error: 10061, An error has occurred while establishing a connection to the server. When connecting to SQL Server 2005, this failure may be caused by the fact that under the default settings SQL Server does not allow remote connections. [SQLSTATE 08001]
2008-01-10 20:57:15 - ! [000] Unable to connect to server '(local)'; SQLServerAgent cannot start
2008-01-10 20:57:46 - ! [298] SQLServer Error: 10061, TCP Provider: No connection could be made because the target machine actively refused it. [SQLSTATE 08001]
2008-01-10 20:57:46 - ! [165] ODBC Error: 0, Login timeout expired [SQLSTATE HYT00]
2008-01-10 20:57:46 - ! [298] SQLServer Error: 10061, An error has occurred while establishing a connection to the server. When connecting to SQL Server 2005, this failure may be caused by the fact that under the default settings SQL Server does not allow remote connections. [SQLSTATE 08001]
2008-01-10 20:57:46 - ! [382] Logon to server '(local)' failed (DisableAgentXPs)
2008-01-10 20:57:46 - ? [098] SQLServerAgent terminated (normally)

Megjegyzem, ugyanezt Named Pipes-szal is tudja, a kérdés az SQL kliens protocol order.

Szóval tényleg létezik a kulcs a HKLM/Software/Microsoft/Microsoft SQL Server/[instancename]/SQLServerAgent/ServerHost helyen, alapból üres, de be lehet állítani szépen a nevét a szervernek. Cluster esetében praktikus mindkét node-on ezt megtenni.

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 :))