Temat brzmi dość zagadkowo, ale nie miałem pomysłu jak go lepiej nazwać. Sytuacja wygląda następująco - mamy (uproszczoną dla celów dydaktycznych ) tabelę w MySQL:
- id (INT)
- name (VARCHAR)
- info (VARCHAR)
- lastmod (DATETIME)
- locked (DATETIME)
Jedno żądanie polega na wybraniu 1 rekordu z bazy (order by lasmod ASC LIMIT 1) i wykonaniu na nim pewnej operacji, która może trwać od 0.5 - 3 sekundy, po czym czas w kolumnie lastmod jest zmieniany na aktualny - więc rekord spada na koniec kolejki. Problem polega na tym, że żądań może być momentami bardzo wiele - nawet kilka na sekundę (a może jeszcze częściej) i gdy nie wybieramy rekordu losowo może się zdarzyć sytuacja w której w kolejnym żądaniu wybierzemy rekord, który jest przetwarzany w żądaniu poprzednim.
Wydawało mi się, że wystarczy w zapytaniu wybierającym rekord dodać warunek omijający aktualnie przetwarzane rekordy w stylu:
WHERE locked > NOW() - INTERVAL 10 MINUTE
i po wybraniu rekordu wykonać zapytanie ustawiające blokadę:
UPDATE tabela SET locked=NOW() WHERE id={ID_WYLOSOWANEGO_REKORDU}
To oczywiście w dużej mierze poprawiło stan rzeczy, natomiast bardzo sporadycznie zdarzają się sytuacje, w których między wybraniem rekordu a ustawieniem blokady wiersz zostanie wybrany raz jeszcze w drugim żądaniu w wyniku czego będzie przetwarzany w 2 wątkach jednocześnie.
Pytanie jak temu zaradzić - czy istnieje jakiś inny sposób zablokowania wiersza?