Szemafor T-SQL-ben

Egy szép napon szembesültem azzal a problémával, hogy alkalmazásszerverek párhuzamos futásuk közben vágják egymás alatt a fát. Az alkalmazások módosítása kicsit fájdalmas lett volna, ezért SQL oldalon kezeltük le a problémát. A kritikus szakaszban egyszerre csak egyvalaki lehet – ezt szokták szemaforral biztosítani. Na, ez történt itt is, csak T-SQL-ben szemaforoztam. Érdekes élmény:

-- SQL 2005 - alapvetően a try-catch-re építünk
WHILE 1 = 1
BEGIN
BEGIN TRY
	CREATE TABLE ##semaphor (a int);
	BREAK;
END TRY
BEGIN CATCH
	WAITFOR DELAY '000:00:03';
	CONTINUE;
END CATCH
END
-- Itt a kritikus szakasz
DROP TABLE ##semaphor

A gondolatmenet egyszerű: van egy globális temptábla (a dupla rácsos linzer jelzi, hogy ezt bárki elérheti, nemcsak a létrehozója), ami a szemafor. Aki létrehozta, az beléphet a kritikus szakaszba, a többiek meg egy helyben ugrálnak, és próbálják létrehozni a táblát. Ennyi.
Felvetődik a kérdés, hogy mi van azzal, aki SQL 2000-t futtat még. Az egyrészt upgrade-elhet :), másrészt pedig használhatja a következő scriptet:

-- SQL 2000-ben az object_id a barátunk
WHILE object_id('tempdb..##semaphor') is not null
BEGIN
WAITFOR DELAY '000:00:03'
END
CREATE TABLE ##semaphor (a int)
-- Itt a kritikus szakasz
DROP TABLE ##semaphor

Mivel a SQL 2000-ben még nincs try-catch, teljesen más logikával kell hozzáállnom: lekérdezem az object_id-ját a temptáblának, ha létezik, akkor várok, ha nem, akkor megcsinálom. Egyetlen gyenge pontja az előzőhöz képest: ha egyszerre ketten látják úgy, hogy nincs ott a temptábla, és megpróbálják létrehozni, akkor az egyik sikerül, a másik pedig elszáll egy szép exception-nel, mert már létezik a tábla. Ezt sajnos nem bírtam lekezelni. Egyébként meglepően gyakran fordul elő ez az eset ahhzo képest, hogy mennyire kicsinek tűnik a valószínűsége.

Leave a comment