webForumDet fria alternativet

Lås på SQL Server

Webbutveckling

2 svar · 288 visningar · startad av kristoffer

Medlem sedan juni 20001 257 inlägg
Frågan#1

Användare A SELECT:ar en post i databasen (för att redigera denna i ett formulär).
Då användare B vill göra samma sak skall detta inte vara möjligt förrän användare A är klar (dvs har gjort en UPDATE eller avbrutit redigeringen).

Det jag vill åstadkomma är alltså att en användare kan låsa en post i databasen så att andra användare inte kan UPDATE:a eller DELETE:a dessa.

Finns det inbyggda funktioner för detta i MS SQL Server?

Medlem sedan mars 2001238 inlägg
#2

MSSQL har inbyggda låsningsfunktioner ja. Jag är inte jätteinsatt i det hela, men här är ett förslag till lösning om du inte redan löst det.

Tänk exempelvis att vi har en tabell med namnet "lock", innehållande id (int, primary key, identity), fn (char), en (char).

Två exempelrader:

1 Sven Svensson
2 Jan Jansson

Skapa två anslutningar i exempelvis Query Analyzer om du har den installerad. Klistra in nedanstående i respektive fönster.

Fönster 1
BEGIN TRANSACTION
SET TRANSACTION ISOLATION LEVEL Repeatable read
SELECT * FROM lock WHERE id = 1

Fönster 2
SET LOCK_TIMEOUT 5000
UPDATE lock SET fn = 'David' WHERE id = 1

Kör koden i fönster 1. Den påbörjar en transaktion, sätter isolation level till Repeatable read (Share locks samt Exclusive locks hålls under hela transaktionen), och sedan gör den en enkel select och begär post 1. Observera att transaktionen inte avslutas ännu.

Över till fönster 2. Kör koden. Den ska vänta maximalt fem sekunder (standard är obegränsat) innan den ger upp ifall den stöter på ett lås. Den försöker nu uppdatera post 1 genom att ändra förnamnet från Sven till David. Men eftersom fönster 1 har en pågående transaktion och en strikt isolation level så är den posten låst och det kommer misslyckas, och efter fem sekunder ge ett felmeddelande. Men testa att byta ut id 1 mot 2 istället. Den posten är inte låst och kan därmed ändras eller raderas.

I fönster 1 avslutar du sedan transaktionen med antingen COMMIT TRANSACTION eller ROLLBACK TRANSACTION. Transaktionen är därmed genomförd eller "tillbakarullad" och post 1 är "upplåst".

Med andra ord: Din webbsida/program/whatever startar en transaktion, sätter lås och hämtar en/flera poster. När personen är klar och ändringarna har gjorts skickas kommandot COMMIT TRANSACTION.

Det som då återstår att fundera på är hur länge MSSQL håller ett lås (om du hypotetiskt aldrig skickar COMMIT TRANSACTION) och hur man eventuellt kan släppa låset efter en viss tidsperiod. Detta har jag dock inget svar på.

Hoppas mitt svammel kan hjälpa lite iaf. Det finns kanske finare lösningar, jag vet inte...

/David

Medlem sedan dec. 200012 464 inlägg
#3

Jag skulle inte rekommendera att försöka koda någon egen låsning. Det största problemet är just det som davids inte har något svar på.

Om man vill undvika dubbla uppdateringar kan man använda sig av en optimistisk metod. Spara de gamla värdena när du läser data från tabellen och jämför dom med de befintliga värdena vid update. Om de skiljer sig så betyder det att någon annan har uppdaterat och i så fall underkänner man denna uppdatering.

256 ms totalt · 4 externa anrop · v20260731065814-full.86ec41c2
121 ms — deklarationer (db)
0 ms — hämta statistik (cache)
132 ms — hämta tråd, inlägg och bilagor (db)
122 ms — ändringar (db)