Mam tabelę w MySQL, która reprezentuje kolejkę linków do przetworzenia. Łącza są przetwarzane przez zewnętrzną aplikację, jedna po drugiej, i ostatecznie usuwane. Jest to kolejka o dużym wolumenie i mam wiele instancji aplikacji do przetwarzania, rozproszonych na kilku serwerach.
Jak mogę się upewnić, że każdy rekord jest wybierany tylko przez jedną aplikację? Czy istnieje sposób na oznaczenie / zablokowanie rekordu?
W tej chwili, aby uniknąć pobierania dwóch lub więcej tego samego linku, zezwalam każdemu wystąpieniu tylko na pobranie określonego zestawu rekordów (na podstawie MOD ich identyfikatora), ale nie jest to przejrzysty sposób na zwiększenie przetwarzania kolejek przyspieszyć, dodając nowe wystąpienia.
Odpowiedzi:
Po pierwsze: MySQL jest jednym z najgorszych możliwych programów do implementacji tego, szczególnie jeśli jest bardzo dynamiczny. Powodem jest to, że silniki takie jak MEMORY i MyISAM mają tylko blokady pełnej tabeli, podczas gdy bardziej odpowiednie silniki, takie jak InnoDB, mają wyższą karę zapisu (w celu zapewnienia właściwości ACID) i są zoptymalizowane pod kątem dostępu do rekordów, które są przestrzennie i czasowo zamknięte (są ustawione na pamięć ). Nie ma też dobrego systemu powiadamiania o zmianach dla MySQL - należy go zaimplementować jako odpytywanie. Istnieją dziesiątki programów zoptymalizowanych do tego zadania .
Powiedziawszy to, widziałem z powodzeniem wdrożenie tego rodzaju dostępu, jeśli wymagania dotyczące wydajności / wydajności nie są bardzo wysokie. Wiele osób nie może sobie pozwolić na wprowadzenie i utrzymanie kompletnego oddzielnego rozwiązania technologicznego tylko dla niewielkiej części logiki biznesowej.
SELECT FOR UPDATE
to jest to, czego szukasz - przeczytaj serializację. Chociaż UPDATE / DELETE zawsze blokuje wiersz podczas uruchomionej transakcji MYSQL, możesz chcieć uniknąć dużej transakcji podczas trwania procesu, więc:MySQL zajmie się blokowaniem wszystkich jednoczesnych zaznaczeń oprócz jednego podczas wybierania wierszy. Ponieważ może to prowadzić do wielu zablokowanych połączeń jednocześnie, początkowa transakcja powinna być jak najmniejsza i starać się przetwarzać więcej niż 1 wiersz na raz.
źródło
Jak wyjaśniłem w tym artykule , MySQL 8 wprowadził obsługę zarówno SKIP LOCKED, jak i NO WAIT.
POMIŃ ZABLOKOWANY jest przydatny do implementacji kolejek zadań (inaczej kolejki wsadowe), dzięki czemu można pominąć blokady, które są już zablokowane przez inne jednoczesne transakcje.
Opcja BRAK CZEKAJ jest przydatna, aby uniknąć czekania, aż równoczesna transakcja zwolni blokady, które również jesteśmy zainteresowani blokowaniem. Bez ŻADNEGO OCZEKIWANIA musimy albo poczekać, aż blokady zostaną zwolnione (w czasie zatwierdzania lub zwolnienia przez transakcję, która obecnie blokuje blokady) lub upłynie limit czasu pobierania blokady. Dlatego BRAK OCZEKIWANIA działa jak limit czasu blokady o wartości
0
.Aby uzyskać więcej informacji na temat SKIP LOCK i BEZ CZEKAJ, sprawdź ten artykuł .
źródło
Zrobiłem coś podobnego z kontrolami DBCC offline (dwa serwery wykonują przywracanie kopii zapasowej, a następnie DBCC checkdb). Jeden serwer zbiera wczoraj wszystkie kopie zapasowe 31 serwerów i umieszcza je w kolejce, a następnie ten serwer i inny ściągają z tej kolejki. Chociaż nie jest to wiele serwerów, metoda powinna pozostać ta sama: Poproś serwer aplikacji, aby uruchomił zapytanie o aktualizację w kolejce, aktualizując pole daty / godziny i pole „serwer aplikacji” z nazwą tego serwera aplikacji lub lepszym, ale jeszcze liczbowym identyfikatorem. Spowoduje to blokadę lub jeśli już blokada z innego serwera uzyskuje następny wiersz, zostanie ona zablokowana i zaczekaj, aż inna aplikacja zakończy pobieranie następnego rzędu. Będziesz wtedy chciał, aby aplikacja pobierała najnowszy rekord z kolejki dla pola aplikacji i pobierała z niego wszelkie potrzebne informacje. Korzystanie z MySQL ”
źródło