Mimo że nie jest to najlepsze rozwiązanie, ponieważ nie ma sposobu, aby zignorować zablokowane wiersze, wybieram losowy i próbuję uzyskać blokadę.
START TRANSACTION;
SET @v1 =(SELECT myId FROM tests.table WHERE status is NULL LIMIT 1);
SELECT * FROM tests.table WHERE [email protected] FOR UPDATE; #<- lock
Ustawienie małego limitu czasu dla transakcji, jeśli ten wiersz jest zablokowany, transakcja jest przerywana, a ja próbuję innej. Jeśli zdobędę zamek, przetwarzam go. Jeśli (pech) ten wiersz był zablokowany, jest on przetwarzany, a blokada jest zwalniana przed upływem mojego czasu, a następnie wybieram wiersz, który został już "przetworzony"! Jednak sprawdzam pole ustawione przez moje procesy (np. Status): jeśli druga transakcja procesu zakończyła się pomyślnie, to pole mówi mi, że praca została już wykonana i nie przetwarzam ponownie tego wiersza.
Każde inne możliwe rozwiązanie bez transakcji (np. Ustawienie innego pola, jeśli wiersz nie ma statusu i ... itd.) Może z łatwością zapewnić warunki wyścigu i pominięte procesy (np. Jeden wątek nagle zginie, przydzielone dane są nadal oznaczone, podczas gdy wygaśnie transakcją;. ref skomentować here
Nadzieja pomaga
+1 stosując limit to dobry pomysł –
W tym przykładzie, jeśli skrypt nagle przerwany po pierwszej aktualizacji, w jaki sposób „oczyścić”. baza danych ze starych procesów? W przeciwnym razie te 100 wierszy nigdy by się nie zajął. –
Dobre pytanie. Zwykle ustawiam tę samą kolumnę lub " stan "kolumna wskazująca pomyślne zakończenie (w ramach transakcji). Następnie, jeśli proces umiera, możesz ustawić parametr process_id dla nieistniejącego procesu z powrotem na NULL, aby inny proces mógł zostać przechwycony. Wolę prace crona w celu oczyszczenia, ale można również włączyć je w proces rozpoczynania nowego procesu. –