438 7. SYSTEMOWE ASPEKTY JĘZYKA SQI.
do. Wartości atrybutów określają więc numer konta oraz bieżące saldo na tym koncie.
Chcemy, aby przykładowa funkcja przelew (} dokonywała przelewu pewnej ustalonej kwoty z jednego konta na inne, o ile jest to możliwe, tzn. o ile saldo z pierwszego konia nie jest niższe od zadanej kwoty. Szkic funkcji przelew () został przedstawiony na rys. 7.10. Instrukcje zapisane w wierszach od 8) do 10) powodują wczytanie wartości salda z pierwszego konta. W wierszu 10) ocenia się, czy saldo na pierwszym koncie jest wystarczające do dokonania przelewu z pierwszego konta na drugie. Jeśli tak, to wykonują się instrukcje z wierszy od 12) do 14), które powodują dodanie zadanej kwoty1 do salda na drugim koncie, oraz instrukcje z wierszy od 15) do 19), które powodują zmniejszenie salda na pierwszym koncie o tę kwotę. Jeśli saldo na pierwszym koncie jest zbyt niskie, to przelewu nie dokonuje się, a użytkownik zostaje o tym powiadomiony w wyniku wykonania instrukcji z wiersza 18).
Zastanówmy się teraz, co się stanie, jeśli po wykonaniu instrukcji z wiersza 14) nastąpi awaria, tzn. albo zepsuje się komputer, albo zostanie uszkodzona sieć między1 bazą danych a komputerem przetwarzającym funkcję. W bazie danych zostanie wówczas zapisane zwiększenie salda na koncie drugim, ale saldo na pierwszym koncie nie zostanie zmniejszone. W wyniku tego bank musi uzupełnić kwotę, która została dopisana do drugiego konta.
□
Zapewnienie sekwencyjności
W praktyce wymaganie, aby działania były przetwarzane sekwencyjnie, jest trudne do wyegzekwowania, po prostu jest ich zbyt dużo i część z nich musi być przetwarzana równolegle. Dlatego mechanizmy zapewnienia se-kwencyjności są dołączane do systemów baz danych i naw et jeśli przetw arzanie odbywa się równolegle, to jego wyniki dla użytkownika wyglądają tak, jakby przetw arzanie było sekwencyjne.
W punkcie 1.2.4 wspominaliśmy, żc jeden zc sposobów zapewnienia właściwego wyniku przetwarzania polega na blokowaniu elementów bazy danych po to, by uniknąć jednoczesnego dostępu do nich. Na przykład, gdyby funkcję Rezerwacja () z przykładu 7.11 napisać tak, że na czas jej działania byłby zablokowany dostęp do relacji Rejsy, to inne funkcje, które nie korzystają z danych tej relacji, mogłyby działać równolegle, ale nic można by uruchomić równolegle drugiego wykonania funkcji Rezerwacja (). A w praktyce, jak wiadomo już z p. 1.2.4, korzystanie z blokad mniejszych niż cała relacja, takich jak bloki lub pojedyncze krotki, umożliwia jeszcze więcej równoległości, można na przykład nawet wykonywać równolegle wywołania tej samej funkcji Rezerwacja ().
Przykład 7.12 dobrze obrazuje ten typ sytuacji, kiedy cały ciąg działań n bazie danych powinien zostać wykonany niepodzielnie, tzn. albo zostań przetworzone wszystkie działania cząstkowe, albo żadne z nich. Dość częst rozwiązuje się ten problem, rezerwując lokalną przestrzeń roboczą, w któri odbywa się całość przetwarzania; dopiero po wykonaniu wszystkich działa zatwierdza się zmiany zapisane w bazie danych i wówczas zmiany te stają si widoczne w bieżącym stanie bazy dla innych funkcji.
Rozwiązanie problemów związanych z szeregowaniem i atomizacji o których była mowa w p. 7.2.1 i 7.2.2, polega na grupowaniu działań na b< zie danych w transakcje. Transakcję tworzy jedno lub kilka działań na bazi danych, które trzeba wykonywać niepodzielnie: albo zostaną przetworzor wszystkie, albo żadne z nich. Poza tym we wczesnych wersjach SQL istniał wymaganie, aby transakcje były wykonywane sekwencyjnie. Jednakże ji w $QL2 osłabiono to wymaganie. Ta sekwencyjność jest przyjmowana przt domniemanie*, ale użytkownik może ograniczyć ten wymóg i określić, któi działania w transakcji mogą być wykonywane sekwencyjnie. W dalszyc rozdziałach poświęcimy w ięcej uwagi temu zagadnieniu.
W jaki sposób zmienia się baza danych podczas transakcji
W różnych systemach transakcje są różnic implementowane. Zdarza się, że w trakcie wykonania transakcji stan bazy danych ulega zmianie. Wówczas, pomimo cofnięcia transakcji, te zmiany były wddoczne dla innych transakcji. Aby uniknąć niekorzystnych konsekwencji, system najczęściej blokuje modyfikowane dane na użytek jednej transakcji i ten chwilowy stan bazy nie jest dostępny dla innych transakcji, aż do momentu jej zatwierdzenia albo cofnięcia. Blokady lub rozwiązania im równoważne są na pewno stosowane wówczas, gdy użytkownik wymaga sekwencyjności.
Jednakże, jak przekonamy się w p. 7.2.4, SQL2 umożliwia wybór sposobu traktowania zmian chwilowych. Można zatem wybrać taki tryb pracy, źc dostęp do danych zmienianych w trakcie transakcji nie jest blokowany, a więc wartości zmieniane są widoczne dla innych transakcji nawet wówczas, gdy zmiany znikną wkrótce, w wyniku pojawienia się instrukcji rollback. A więc to projektant decyduje, które zmiany chwilowe są widoczne dla innych transakcji, a które nie. Wszystkie implementacje SQL zawierają mechanizmy, takie jak na przykład blokady, które umożliwiają ochronę dostępu do danych uczestniczących w transakcji.
’ Aczkolwiek w niektórych implementacjach stosuje się mniej restrykcyjne założenia.