Opóźnienie obsługi w transakcjach MySQL
Próbuję dowiedzieć się, jak poprawnie skonfigurować transakcję w bazie danych i uwzględnić potencjalne opóźnienie.
UstawićW moim przykładzie mam tabelęusers
, keys
, gdzie każdy użytkownik może mieć wiele kluczy, a aconfig
tabela określająca, ile kluczy każdy użytkownik może mieć.
Chcę uruchomić procedurę składowaną, która:
oblicza, czy dany użytkownik może zażądać klucza.uzyskać dostępny, nieodebrany klucz.próbuje odkupić klucz dla danego użytkownika.pseudokodem procedury byłoby:
START TRANSACTION
(1) CALL check_permission(...,@result);
IF (@result = 'has_permission') THEN
(2) SET @unclaimed_key_id = (QUERY FOR RETURNING AVAILABLE KEY ID);
(3) CALL claim_key(@unclaimed_key_id);
END IF;
COMMIT;
Problem, na który wpadam, polega na tym, że kiedy symuluję opóźnienie po kroku1
, (używającSELECT SLEEP(<seconds>)
), dany użytkownik może wykupić wiele kluczy, gdy ma tylko uprawnienia do odkupienia jednego, uruchamiając procedurę w wielu sesjach, zanim pierwsza procedura zakończy sen (co również ma na celu symulację opóźnienia)
Oto kod dlastoły iprocedury (uwaga: dla małego przykładu nie zawracałem sobie głowy indeksami i obcymi kluczami, ale oczywiście używam tych w rzeczywistym projekcie).
Aby zobaczyć mój problem, po prostu ustaw tabele i procedury w bazie danych, a następnie otwórz dwa terminale mysql, aw pierwszym uruchom to:
CALL `P_user_request_key`(10,1,@out);
SELECT @out;
A potem szybko (masz 10 sekund) w drugim uruchomieniu:
CALL `P_user_request_key`(0,1,@out);
SELECT @out;
Oba zapytania zostaną pomyślnie zwróconekey_claimed
i UżytkownikBob
skończy się przypisaniem mu 4 kluczy, chociaż maksymalna wartość w konfiguracji jest ustawiona na 3 na użytkownika.