Napisany przez: Zbłąkany 8.07.2004, 23:36:49
Pytanie może banalne, ale nie mogę nigdzie znaleźć rozwiązania: czy Microsoft SQL Server 2000 (msde 2000 sp3a) obsługuje blokowanie tabel, coś takiego jak LOCK TABLES w mySQL?? niestety nie znalazłem manuala do Microsoft SQL Server 2000 no i nie mam kiedy podjechać do Empiku aby sprawdzić w książce...
---Edited---
... trochę poszperałem, poprzeglądałem internet od tego czasu, bylem w empiku i niestety nie mieli na stanie tej książki , ale oszczędzę tego innym co go nie mają tak dużo jakby chcieli, lub dostępu do internetu ...
W kwestii wyjaśnienia: wszystkie informacje przeze mnie prezentowane, są pobrane z kopii rozmowy z Markiem Adamczukiem z http://mssqlserver.org.pl, adres do topicu znajduje się http://mssqlserver.org.pl/webboard/display_topic_threads.asp?ForumID=4&TopicID=175&PagePosition=1 (niestety aby przeglądać to forum trzeba się zarejestrować), jeśli ktoś będzie szukał dodatkowych informacji proponuję zajrzeć do Microsoft SQL Server BOL można pobrać http://www.microsoft.com/downloads/details.aspx?FamilyID=a6f79cb1-a420-445f-8a4b-bd77a7da194b&DisplayLang=en (cenne źródło informacji na temat SQL Server 2000 i msde 2000).
Tyle tytułem wstępu czas przejść do właściwych informacji:
Aby założyć blokadę na czas danej operacji (czyt. poleceń DELETE, INSERT, SELECT, UPDATE) potrzebujemy znać Locking Hints (po spolszczeniu HINT-y)
oraz wiedzieć do czego służą blokady tabel i poznać ich zasadę działania w Microsoft SQL Server 2000.
Najpierw przedstawię wykaz kilku HINT-ów:
- HOLDLOCK - Trzyma blokadę do końca transakcji (czyt. do końca wykonania tranzakcji, ew. do końca wsadzania danych do tabeli), wg mnie najlepiej używać jeśli nie chemy aby przy odczycie danych z tabeli ktoś inny jej nie zmodyfikował. Jest równoważna z SERIALIZABLE.
- READCOMMITED - Standardowa blokada do odczytu, kończy się w momencie zakończenia odczytywania z danej tabeli danych.
- TABLOCK - Wymusza objęcie blokadą całej tabeli.
Microsoft SQL Server 2000 blokuje każdą tranzakcję (czyt. zapytanie do bazy danych) swoim systemem.
... Dzieje się to automatycznie - transakcja blokuje zasoby których używa, o ile nie zostały zablokowane wcześniej innym niezgodnym lockiem. Nie zawsze blokowana jest cała tabela i nie wszystkie blokady powodują niemożność wykonania wszystkich innych operacji na zasobie. ...Jeżeli chcemy założyć blokadę niestandardową na jakaś tabele, której pobieramy dane poleceniem SELECT to kod wyglądałby tak:
<?php
//connect do serwera SQL
$query = \"BEGIN TRAN; SELECT * FROM jakas_tabela [ WITH ( < table_hint > [ ,...n ] ) ]; COMMIT TRAN;\";
$exec = http://www.php.net/mysql_query($query);
?>
Objaśnienie: BEGIN TRAN i COMMIT TRAN zapobiegają dopisaniu jakiejkolwiek wartości do każdej tabeli w bazie. Jeżeli chcielibyśmy zablokować tabele, tak aby żadne dane nie zostały dodane w czasie pobierania przez nas danych z jakiejś tabeli, na czas wykonywania kilku (ew. większej liczby) zapytań, to przed pierwszym zapytaniem musimy wstawić BEGIN TRAN, a po ostatnim COMMIT TRAN, by zwolnić blokadę na bazie.
Żeby blokada na tabelę zadziałała trzeba zdefiniować HINT-y, parametr WITH można pominąć, ale wtedy trzeba i tak umieścić listę HINT-ów w nawiasie okrągłym (z przecinkami), zaraz za nazwą tabeli, co z resztą ma miejsce również jak używamy WITH (wtedy jest to badziej czytelniejsze zapytanie, dla kogoś kto widzi takie pierwszy raz) też trzeba listę HINT-ów umieścić w nawiasie okrągłym (z przecinkami).
Przykład:
Mamy tabele:
lockme
id INT PRIMARY KEY; opisVARCCHAR(50);
W niej jeden wiersz id=1, opis=ktoś_go_dodał.
Napiszmy skrypt, który będzie pobierał ten wieersz i przy okazji zapobiegał zmodyfikowaniu go:
<?php
//connect do serwera SQL
$query = \"BEGIN TRAN; SELECT * FROM lockme WITH (HOLDLOCK, TABLOCK); COMMIT TRAN\";
$exec = http://www.php.net/mysql_query($query);
?>
Wykaz umieszczania HINT-ów w zapytaniach INSERT, UPDATE oraz DELETE.
- Dla polecenia INSERT:
INSERT INTO nazwa_tabeli WITH ( < table_hint_limited > [ ...n ] ) (lista_pól) VALUES (wartości_pól);
Obowiązują tutaj wszystkie HINT-y za wyjątkiem: READPAST, NOLOCK oraz READUNCOMMITTED. - Dla polecenia UPDATE:
UPDATE nazwa_tabeli WITH ( < table_hint_limited > [ ...n ] ) SET nazwa_kolumny1='wartość1', nazwa_kolumny2='wartość2';
Obowiązują tutaj wszystkie HINT-y za wyjątkiem: READPAST, NOLOCK oraz READUNCOMMITTED. - Dla polecenia DELETE:
DELETE FROM nazwa_tabeli WITH ( < table_hint_limited > [ ...n ] ) WHERE warunki;
Obowiązują tutaj wszystkie HINT-y za wyjątkiem: READPAST, NOLOCK oraz READUNCOMMITTED.
Na koniec podam listy wszystkich HINT-ów i HINT-ów limitowanych używanych:
Wszystkie HINT-y:
- FASTFIRSTROW
- HOLDLOCK
- NOLOCK
- PAGLOCK
- READCOMMITTED
- READPAST
- READUNCOMMITTED
- REPEATABLEREAD
- ROWLOCK
- SERIALIZABLE
- TABLOCK
- TABLOCKX
- UPDLOCK
HINT-y limitowane:
- FASTFIRSTROW
- HOLDLOCK
- PAGLOCK
- READCOMMITTED
- REPEATABLEREAD
- ROWLOCK
- SERIALIZABLE
- TABLOCK
- TABLOCKX
- UPDLOCK
Zainteresowanych co do roli pozostałych HINT-ów, których nie opisałem w swoim spisie na początku polecam
Microsoft SQL Server BOL oraz
książkę Inside of SQL Server 2000 autorstwa Kalen Delaney