Cz. 1: Zlecenia asynchroniczne i MySQL
Disclaimer (Zastrzeżenie):Pamiętaj proszę, że w tym artykule celowo pominąłem większość wewnętrznych szczegółów naszego produktu. W niektórych miejscach zastosowałem również uproszczone wyjaśnienia dotyczące indeksów MySQL, zwłaszcza tam, gdzie szczegółowe opracowania są już łatwo dostępne w sieci (w odpowiednich miejscach znajdziesz linki).
W tej pierwszej części wpisu najpierw krótko nakreślę kontekst tego, jak realizujemy pewne procesy w Productive. Następnie zwięźle wyjaśnię, czym są deadlocki (zakleszczenia), po czym przejdę do opisu podejścia, które zastosowaliśmy, aby je naprawić. W drugiej części, która ukaże się wkrótce, pokażę inne rozwiązanie, które wdrożyliśmy w celu rozwiązania problemu deadlocków w naszym środowisku end-to-end.
Zlecenia asynchroniczne w Productive
W Productive do planowania zadań asynchronicznych wykorzystujemy Sidekiq. Niektóre z tych zadań odpowiadają za wysyłanie e-maili do użytkowników, gdy ci nie śledzą swojego czasu pracy. Inne to zadania wsadowe (batch jobs), które muszą zaktualizować pewne dane finansowe, skopiować określone obiekty w sposób bezpieczny transakcyjnie itp. Kilka miesięcy temu zaczęliśmy zauważać gwałtowny wzrost liczby deadlocków w naszej aplikacji. W szczególności, zakleszczenia te zaczęły pojawiać się w przypadku wsadowych zadań Sidekiq, które muszą przetwarzać dużą liczbę stosunkowo ciężkich transakcji bazodanowych.
Czym są deadlocki (zakleszczenia)?
Deadlocki bazodanowe (zakleszczenia) występują, gdy dwie transakcje nie mogą kontynuować działania, ponieważ jedna z nich utrzymuje blokadę (lock), której potrzebuje druga. Same w sobie deadlocki nie są niczym złym, o ile nie wpływają na bazę danych w taki sposób, że uniemożliwiają całkowite przetworzenie niektórych transakcji. Konieczne jest jednak posiadanie mechanizmu ponawiania prób dla transakcji, które uległy zakleszczeniu. Zazwyczaj wystarczy ponowić tylko drugą transakcję (tę, która spowodowała deadlock), ponieważ MySQL przerywa tylko tę transakcję, aby zwolnić blokadę, pozwalając pierwszej transakcji na kontynuację.