Jak testujesz warunki wyścigu w bazie danych?

30

Próbuję napisać kod bazy danych, aby upewnić się, że nie podlega warunkom wyścigu, aby upewnić się, że zablokowałem prawidłowe wiersze lub tabele. Ale często zastanawiam się: czy mój kod jest poprawny? Czy można zmusić do manifestacji jakiekolwiek istniejące warunki wyścigu? Chcę mieć pewność, że jeśli tak się stanie w środowisku produkcyjnym, moja aplikacja zrobi właściwą rzecz.

Ogólnie wiem dokładnie, które współbieżne zapytanie może powodować problem, ale nie mam pojęcia, jak zmusić je do jednoczesnego uruchomienia, aby sprawdzić, czy zdarzy się prawidłowe zachowanie (np. Użyłem właściwego typu blokady), czy właściwe błędy to wyrzucony itp.

Uwaga: używam PostgreSQL i Perla, więc jeśli nie można na nie udzielić ogólnej odpowiedzi, prawdopodobnie powinien zostać ponownie oznaczony jako taki.

Aktualizacja: Wolałbym, gdyby rozwiązanie było programowe. W ten sposób mogę pisać automatyczne testy, aby upewnić się, że nie ma regresji.

ksenoterracid
źródło
Czy przez „warunek wyścigu” masz na myśli „impas”?
Gajusz
2
@ Gaius ... nie, choć wierzę, że jest to jeden z możliwych warunków wyścigu
ksenoterracid
@ Warunki wyścigu Gaiusa w bazie danych polegałyby na upuszczaniu tabeli przed jej utworzeniem lub aktualizacji wiersza przed jej wstawieniem. Generalnie wyobrażam sobie, że logika aplikacji jest obsługiwana poza samą bazą danych.
Mark D
aktualizujesz wiersz przed wstawieniem? to nie spowodowałoby problemu z db. żaden warunek wyścigu nie byłby taki, jak pobranie wiersza i zaktualizowanie go, ale zlecenie aktualizacji przez innego użytkownika po pobraniu wiersza, ale przed przetworzeniem aktualizacji.
ksenoterrakid
1
@MarkD - Nie. Istnieje wiele rodzajów warunków wyścigu, które wynikają z nieprawidłowego kapsułkowania atomowej jednostki pracy w bazie danych. Oto przykład. Pamiętaj: „stan wyścigu lub zagrożenie wyścigu jest wadą w systemie lub procesie elektronicznym, w którym wynik lub wynik procesu jest nieoczekiwanie i krytycznie zależny od sekwencji lub czasu innych zdarzeń ”. ( źródło )
Nick Chammas

Odpowiedzi:

11

Robię to cały czas z moimi modułami T-SQL.

Zasadniczo wszystko, co musisz zrobić, to uruchomić moduły z dwóch lub więcej połączeń w pętli przez kilka minut . Zazwyczaj wszystkie potencjalne problemy są ujawniane w ciągu kilku minut, przy założeniu, że masz SQL Server z przyzwoitymi procesorami.

Napisałem kilka przykładów tu i tutaj .

AK
źródło
4

Zwykle pracuję z narzędziem wiersza poleceń RDBMS, po prostu uruchomiłem 2 (lub więcej) instancji CLI. Następnie możesz odtwarzać jeden po drugim i jako wyścig (który wyglądałby jak RPG akcji) instrukcje SQL wysyłane przez warstwę aplikacji. Powinieneś eksperymentować / czuć działanie systemów blokujących, ponieważ Twój CLI „zawiesi się” trochę, czekając na zwolnienie blokad z innych CLI.

Jeśli brzmi to jak błoto, nie wahaj się tego powiedzieć ;-)

Julien
źródło
czy możesz podać przykład krok po kroku? i czy można napisać testy programowe, aby zrobić to samo?
ksenoterracid
1

Warunki wyścigu wymagają wielu wątków wykonania, dlatego aby przeprowadzić test jednostkowy, musisz mieć możliwość rozpoczęcia jednego lub więcej wątków. W Oracle użyłbym DBMS_Scheduler do uruchomienia procesu symulującego drugiego użytkownika. Jeśli PostgreSQL / Perl ma sposób na programowe zainicjowanie drugiego procesu, powinieneś być w stanie zrobić coś takiego:

Proces 1 Proces 2

Rozpocznij proces 2. >>                            
Opóźnij, aby pozwolić 2 na wykonanie swojej pracy. 
. Zablokuj wiersze lub zmień dane.
. Opóźnij, aby pozwolić 1 na wykonanie swojej pracy.
Spróbuj zablokować wiersze lub zmienić dane. .
Sprawdź, aby upewnić się, że została wykonana właściwa obsługa. .
Kończy się. .
                                                Kończy się.

Dobrze jest myśleć, jak radzić sobie z warunkami wyścigowymi, a co ważniejsze, jak je testować.

Leigh Riffel
źródło
Nie opisałbym takich testów jako testów jednostkowych, ponieważ testy jednostkowe muszą zawsze przebiegać dokładnie w ten sam sposób. Warunki wyścigu zawodzą w nieregularnych procesach, nie za każdym razem w dokładnie taki sam sposób.
AK
@AlexKuznetsov Masz rację, że Nieoczekiwane warunki wyścigu mogą pokazywać je sporadycznie, jednak OP odnosi się do Oczekiwanych warunków, które według niego będą działały. Te specyficzne warunki można dokładnie odtworzyć, a sposób postępowania zweryfikować za pomocą testu jednostkowego.
Leigh Riffel
-2

Dopóki blokujesz rzędy, nie powinieneś być w stanie wyścigowym, ponieważ zwykle dzieje się tak, gdy nie ma blokady.

Ale możesz zostać zakleszczony, jeśli jedno pytanie zbyt długo blokuje twoje pytanie.

Jest to trudne do przetestowania, ponieważ czas zapytań może się zmieniać, gdy baza danych rośnie.

Zapytania, które działają dobrze przy 100 000 wierszy danych testowych, wykraczają poza tabelę przy 10 000 000 wierszy.

Tego rodzaju problem może być bardzo trudny do znalezienia z wyprzedzeniem, ale wiele baz danych ma pewną metodę identyfikowania wolnych zapytań.

Korzystając z tego normalnie, powinieneś być w stanie wychwycić wszelkie zapytania, które mają kłopoty, z dużym ostrzeżeniem.

Jeśli sami sobie zamkniesz, to inna historia, ale nie mogę pomóc.

Nick Chammas
źródło
@darioo lol Myślałem, że może to skrót od czegoś ... idk, co miałby na myśli, mówiąc „zrób to sam”, jeśli nie chce używać ORM, sprawdziłem kod moich wyników ORM, to na pewno nie robi blokowanie w prawo. To jest jeden z powodów, dla których chciałbym móc przetestować potencjalne scenariusze wyścigowe.
xenoterracide
Tak, miałem na myśli własny i zwykle sterownik bazy danych obsługuje blokowanie, wiersz, tabelę lub ewentualnie pole, ale otwieram się na możliwość użycia DB, który nie obsługuje blokowania;)
.. Jestem prawie pewien, że jeśli mam transakcję z wieloma select for update
wyciągami,