Technet SQL üzemeltetői nap előadások

A szeptember 24-i Technet üzemeltetői szemináriumon tartott előadásom – a többiekével együtt – megtalálható a Technet honlapon, a demóscriptekkel együtt. Akit érdekel, ITT találja.

Mire jó a snapshot

A Technet üzemeltetői szemináriumon beszéltem többek között a database snapshotról is, és a felkészülés során egy kicsit belementem a málnásba. Lúzerségemet büszkén felvállalva megosztom mindenkivel, nehogy más is kitalálja ezt a bénázást.
A database snapshot egy olyan read-only adatbázis, amit egy meglévő adatbázis (ez a forrásadatbázis) alapján hozunk létre, és a forrásadatbázisnak a snapshot készítésekori állapotát tartalmazza. Létrehozása nem igényel erőforrást, fenntartása igen. Létrehozáskor ugyanis az SQL Server sparse file-okként hozza létre a fájljait, azaz igazából nem foglal helyet, mert csak azokat a lapokat tartalmazza, amik megváltoztak a forrásadatbázisban. Ez a copy-on-write nevű varázslat, azaz a snapshot tulajdonképpen készít egy backupot magának a forrásadatbázis lapjairól, mielőtt azok megváltoznának. A snapshotnak amellett, hogy egy múltbeli állapotot elérhetővé tesz, van egy másik nagyon előnyös tulajdonsága: segítségével vissza lehet állni az általa tárolt állapotra.
Egy adatbázisról gyakorlatilag akárhány snapshotot tudunk készíteni, de a snapshotnak megvannak a korlátai is: Először is, a snapshot teljesen függ a forrásadatbázistól. Ha a forrásadatbázis elpusztul, vele hal a snapshot is, mivel az adatainak az a része, ami nem változott, csak a forrásadatbázisban található meg. Ebből következik az, hogy nem alkalmas a backup pótlására.
Egy adatbázisról készíthetünk rengeteg snapshotot, ezek egymástól teljesen függetlenek lesznek. Azaz ha egy forrásadatbázisról készítünk tíz snapshotot, minden egyes lap változás a forrásadatbázisban tizenegy írást fog generálni – minden snapshotban egyet, plusz a forrásadatbázisban egyet. Ennek már lehet hatása a teljesítményre. Ráadásul ha vissza akarunk állni valamelyik snapshotra, akkor az összes többit el kell dobnunk. Ez az apró kellemetlenség abból ered, hogy a snapshotolt adatbázist nem lehet restorolni, márpedig a snapshotra való visszaállás erősen hasonlít egy restore-ra, konkrétan azt írjuk bele a SSMS-be, hogy RESTORE DATABASE ForrasAdatbazis FROM SNAPSHOT Snapshot. Vagy valami hasonló.
Tehát az az elképzelésem, hogy az adatbázisról készítek egy snapshotot egy változtatás előtt, majd ha vissza kell állni, előtte is készítek egy snapshotot, meglehetősen kivitelezhetetlen. Próbáltam tovább csavarni a dolgot: ha mirrorozva van az adatbázis, akkor a mirrorról csinálok egy snapshotot visszaállás előtt, és akkor… eszembe jutott az amikor mirrorozott adatbázist kellett restore-olnom. Először tükröt kell törni, mert a mirrorozott adatbázist sem lehet restore-olni. Végül is ez lett a végállomás: tükörtörés, és amikor a restore elindul, felhozom online-ba a mirrort, és ott a visszaállás előtti utolsó adat. Persze addig nincsen mirrorom, de az akkor amúgy sem lenne. Kicsit nyakatekert, kicsit savanyú, de a mienk!
Én meg majd legközelebb elolvasom a Books Online-t, tényleg :)

@@IDENTITY vs SCOPE_IDENTITY() (Ami a Technetről lemaradt)

A tegnapi Technet SQL üzemeltetői konferencián egy vödör fontos dolog kimaradt az előadásból, idő és szervezettségem hiányában.Ezeket szépen sorban meg fogom majd itt írni, valahol elsz hozzá kis demó is – vagy itt, vagy a Technet portálon.
Az első a listán azon gondolatom kifejtése, hogy a @@IDENTITY legépelésekor sokszor a fejlesztő a SCOPE_IDENTITY() függvényt kívánta használni, csak nem ismerte. Miért gondolom ezt? Mert a @@IDENTITY a sessionben legutoljára letépett identity értéket adja vissza, míg a SCOPE_IDENTITY() csak az adott scope-ban tevékenykedik, azaz legfontosabb vívmányként nem foglalkozik a triggerekkel meg efféle bohóságokkal, az általuk húzott sorszámokat ignorálja. Amikor az identity oszlop értékét beszúrás után idegen kulcsként szeretné használni a fejlesztő, akkor ez a különbség fontos lehet. De inkább nézzünk egy példát: Készítsünk egy táblát, amiben felhasználók vannak nyilvántartva.

USE tempdb

CREATE TABLE Alap (
	userid int identity(10000,1),
	username nvarchar(20) not null
	)
-- szúrjunk is be egyet
INSERT INTO Alap VALUES('Erik')
SELECT @@IDENTITY, SCOPE_IDENTITY()

Az eredmény nem meglepő: 10000 és 10000.
Most döntsünk úgy, hogy naplózni akarjuk a táblába való beszúrásokat:

-- a naplótábla...
CREATE TABLE Naplo (
	naploid int identity(1,1),
	uj_username nvarchar(20),
	felhasznalo varchar(128),
	ido datetime
	)
GO
-- ...és a trigger
CREATE TRIGGER Figyelunk ON Alap
FOR INSERT
AS 
	INSERT INTO Naplo
	SELECT username, suser_name(), getdate() from inserted

-- és most szúrjunk be még egyet:

INSERT INTO Alap VALUES('Erik')
SELECT @@IDENTITY, SCOPE_IDENTITY()

Az eredmény a nem meglepő 1 és 10001. Mi történt? A @@IDENTITY visszaadta a legutolsó letépett sorszámot, a napló tábla 1-ét, hiszen a fent iegy insert parancs hatására tulajdonképpen két insert hajtódott végre: egy olyan, amit mi akartunk, és egy olyan, amit a trigger akart. A SCOPE_IDENTITY() viszont csak a mi parancsunkat vette figyelembe, a triggert ignorálta.
Ezek után mindenki maga eldöntheti, hogy mikor melyiket szeretné használni.

UNIQUE és több NULL

(This article has an English version…)
Ha szeretnénk biztosítani azt, hogy egy oszlop értékei mind egyeidek legyenek, akkor használhatjuk a UNIQUE kulcsszót (akár constraint, akár index formában), hogy ezt kierőszakoljuk. Ez eddig szép és jó, de mi a helyzet a NULL értékekkel? Egy NULL-t simán be tudunk szúrni (ez ugye a nagy különbség a UNIQUE és a PRIMARY KEY között, utóbbi nem enged semmilyen NULL-t), de mi van, ha sok NULL-t akarok bepakolni? Continue reading ‘UNIQUE és több NULL’ »

UNIQUE INDEX vs multiple NULL values

In Microsoft SQL Server, if you want to make sure that a column contains no duplicates, you can use the UNIQUE keyword to enforce this constraint, either by creating a unique index or by adding a unique constraint to the column. It’s very useful and nice, but… What about NULL values? I mean, obviously, you can insert the first NULL value, but what if you have more null values and you need to enforce only the uniqueness of the non-null values? Continue reading ‘UNIQUE INDEX vs multiple NULL values’ »