SQL transakcje

0

Mam do wykonania zadanie z transakcji.Jednak za bardzo nie wiem jak mam go wykonać, czy ktoś by mógł wyjaśnić?Jak dobrze słyszałem trzeba odpalić dwóch klientów bazy danych i jakoś sprawdzić kiedy nastąpi zawieszenie transakcji.Ktoś dla przykładu mógłby opisać jak wykonać 1 przykład

link do zadania (druga strona)

http://157.158.51.7/bdsp/Wybrane_problemy.pdf

Z góry dziękuje za pomoc

0

Spróbuję odpowiedzieć, ale mam nadzieję, że ktoś bardziej doświadczony się również wypowie i zweryfikuje.

Polecenie ustawienia poziomu izolacji serializable i repeatable read nie zezwala na tzw. niepowtarzalne odczyty, czyli kiedy transakcja 1 wywołuje zapytanie select, następnie transakcja 2 modyfikuje dany wiersz, a następnie transakcja 1 ponownie wywołuje zapytanie select to "odkrywa", że wiersz się zmienił ale nie potrafi wyjaśnić jak. Właśnie serializable i repeatable read nie dopuszczają do niepowtarzalnych odczytów, więc prawdopodobnie wtedy nastąpi zawieszenie transakcji. To jest odnośnie przykładu (A) i (B) w podanym zadaniu.

Oprócz wyżej wymienionych występują jeszcze fantomy i brudne odczyty.

Fantomy - pojawianie T1 odczytuje dane, T2 wstawia nowe dane, a następnie T1 ponownie je odczytuje to z punktu widzenia T1 pojawiły się tzw. "fantomy", i tylko serializable nie dopuszcza do fantomów.

Brudne odczyty - Kiedy T1 modyfikuje wiersz, T2 czyta zmodyfikowany wiersz, następnie T1 wycofuje zmianę, kolejny odczyt T2 jest brudnym odczytem. Read Commited, Repeatable Read i Serializable nie dopuszczają do brudnych odczytów.

Read Uncomitted dopuszcza zarówno do fantomów, niepowtarzalnych odczytów jak i do brudnych odczytów.

0

Z tego, co widzę, potrzebujesz uruchomić równolegle dwa zadania tak, aby jedno z nich zajęło zasób potrzebny drugiemu. Nie napisałeś, o jaką bazę chodzi. Gdyby to był ms sql, to w miejscach oznaczonych przez preceptora wytłuszczonymi literami w nawiasach wpisałbym np:

wait for delay "00:02"

. Czyli jeden ze skryptów zająłby zasób i zatrzymałby się. Wtedy spokojnie uruchomiłbym drugi i zobaczyłbym, co się dzieje.

0

Z tego, co widzę, potrzebujesz uruchomić równolegle dwa zadania tak, aby jedno z nich zajęło zasób potrzebny drugiemu. Nie napisałeś, o jaką bazę chodzi. Gdyby to był ms sql, to w miejscach oznaczonych przez preceptora wytłuszczonymi literami w nawiasach wpisałbym np:

waitfor delay "00:02"

. Czyli jeden ze skryptów zająłby zasób i zatrzymałby się. Wtedy spokojnie uruchomiłbym drugi i zobaczyłbym, co się dzieje.

0

A jeżeli chodzi o kolejność to wpisuje to od góry do dołu?
begin transaction; 1 klient
begin transaction; 2klient
select * from zespoly; 1 klient
(A) 2 klient
update zespoly set 2 klient
nazwa_zesp=’Igrek’ where nr_zesp=1; 2 klient
(B) 1 klient
select * from zespoly; 1 klient
rollback; 1 klient
rollback; 2 klient

0

Chyba się nie rozumiemy. Opiszę to inaczej.

Po pierwsze potrzebujesz użyć czegoś, co spowoduje, że wykonywanie zawiesi się na przez Ciebie określony czas. W ms sql użyłbym

waitfor delay

. Podany prze ze mnie poprzednio parametr tego polecenia powoduje zawieszenie wykonywania na 2 minuty. Jak Twojej bazie, bo jakoś nie chcesz się przyznać, w jakiej, robi się takie zawieszenie, to nie wiem. Jeśli to nie jest ms sql i nie ma w nim waitfor delay

, to może jak przestaniesz się wstydzić i podasz, jakiego silnika bazodanowego używasz, to ktoś inny Ci pomoże.

Po drugie, jak __ja__ rozumiem Twojego preceptora, to masz do zrealizowania trzy zadania (każde wielokrotnie) sprawdzając w nim różne poziomy izolacji. O poziomach izolacji napisał Ci Krwawy Lew. Doczytaj sobie w manualu, ale myślę, że po przeprowadzeniu, a przed opisaniem zaleconych testów.

Po trzecie to za zadanie pierwsze rozumiem  to, co jest pomiędzy pierwszą a drugą pozioma kreską, czyli:
```sql
 
begin transaction;                                           begin transaction;
select * from zespoly;
                                                                    (A)
                                                                   update zespoly set 
                                                                   nazwa_zesp=’Igrek’ where nr_zesp = 1;
(B)
select * from zespoly;
rollback;                                                        rollback;

i jak widać po lewej jest skrypt pierwszej transakcji, a po prawej drugiej.

Ja przygotowałbym z tego dwa skrypty, pierwszy:

begin transaction;

select * from zespoly;

waitfor delay "00:02";

select * from zespoly;

rollback;

oraz drugi:

begin transaction;

waitfor delay "00:02";

update zespoly set 
nazwa_zesp=’Igrek’ where nr_zesp = 1;

rollback;

ustawił pierwszy z sprawdzanych w tym teście poziomów izolacji i uruchomił skrypt pierwszy i, nie czekając aż się skończy, od razu drugi (czyli równoległe wykonanie) i patrzył,l co się dzieje. Potem kolejny poziom izolacji i znowu uruchomienie obu skryptów, potem trzeci i ...
A potem analogicznie kolejne zadania.

0

zapomniałem całkiem jest to MySQL.Dzięki za pomoc jeszcze nie wiem czy będzie to działać bo teraz szukam odpowiednika waitfor delay dla mysql

Edit:zmieniłem tak jak powinno wyglądać dla mysql.Jednak za każdym razem obie się wykonują a dla żadnej efektu nie widać. Próbowałem dla read uncommitted , committed i serializable w rożnych wariantach. Wiem że dla transakcji 1 serializable a dla drugiej read uncommitted powinno inaczej zadziałać niż np gdy jest ustawione 2x read uncommitted

1 skrypt
Start transaction;

SELECT * FROM zespoly;
Do sleep(10);

SELECT * FROM zespoly;

ROLLBACK;

2 skrypt

Start TRANSACTION;

Do sleep(10);

UPDATE zespoly SET
nazwa_zesp='Igeerek' WHERE nr_zesp = 1;

ROLLBACK;

0

Nie chciałem pisać - mysql to nie moja bajka. No ale skoro nikt nic nie napisał...
Jak przeczytałem, parametr podawany do sleep to sekundy. Myślę, że każdy silnik bazodanowy ma (w zależności od silnika może się to różnie nazywać) timeout. Przynajmniej dla transakcji. I myślę, że u Ciebie jest to około 1 minuty. I prawdopodobnie skrypt spokojnie poczekał te 10 sekund, w czasie których drugi skrypt zajmował zasób. Gdyby czas oczekiwania przekroczył ustawiony w silniku timeout, to coś byś zobaczył. Czyli sugeruję 100 zamiast 10.

0

Miałem bardzo podobne zadanie na zajęciach. My olaliśmy sprawę z delayami, zamiast tego odpalaliśmy(execute!) po kolei każdy wiersz(bodajże kombinacją ctrl+F5).
Kod do pierwszego klienta:

 SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED
SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED
SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ
SET SESSION TRANSACTION ISOLATION LEVEL SERIALIZABLE
select @@tx_isolation
--------------------
-- Transaction 1a
--------------------
begin; -- 1
-- (A) --
select * from students; -- 4
rollback; -- 6
--------------------
-- Transaction 1b
--------------------
begin; -- 1
select * from students; -- 3
-- (C) --
select * from students; -- 5
-- (D) --
select * from students; -- 7
rollback; -- 8
--------------------
-- Transaction 1c
--------------------
begin; -- 1
select * from students; -- 3
-- (F) --
update students set student_name='ZZ1' where student_id=1; -- 5
rollback; -- 7

Oraz do drugiego:

 SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED
SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED
SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ
SET SESSION TRANSACTION ISOLATION LEVEL SERIALIZABLE
select @@tx_isolation
--------------------
-- Transaction 1a
--------------------
begin; -- 1
-- (A) --
select * from students; -- 4
rollback; -- 6
--------------------
-- Transaction 1b
--------------------
begin; -- 1
select * from students; -- 3
-- (C) --
select * from students; -- 5
-- (D) --
select * from students; -- 7
rollback; -- 8
--------------------
-- Transaction 1c
--------------------
begin; -- 1
select * from students; -- 3
-- (F) --
update students set student_name='ZZ1' where student_id=1; -- 5
rollback; -- 7

Cyferki po prawej oznaczają kolejność, czyli np. dla izolacji read uncommitted, odpalamy dany wiersz u obu klientów, następnie zaczynamy od cyferki 1(czyli begin - zaznaczamy i ctrl +F5), itd.

1 użytkowników online, w tym zalogowanych: 0, gości: 1