Já teda nevím, co umí a neumí MySQL, PostgreSQL umí serializované transakce, takže tohle je vyřešeno buď přímo standardní transakční izolací (a opravdu to bezpečně funguje) nebo ještě druhá varianta, která v některých případech je přímo vhodná pro stavbu atomické fronty a to je SELECT FOR UPDATE SKIP LOCKED.
https://www.postgresql.org/docs/17/sql-select.html#SQL-FOR-UPDATE-SHAREFunguje to tak, že příkaz SELECT FOR UPDATE automaticky dá zámek pouze na ty řádky, které vyhovují WHERE. Takže SKIP LOCKED tyto řádky automaticky přeskočí.
Já si takto implementoval atomickou frontu, kde nebylo nutné udržet pořadí (ale stále jde mít ORDER BY) a každý řádek bylo nutné zpracovat pouze jednou a skutečně jednou a mít o tom záznam.
Takže něco jako WHERE todo=True, a v UPDATE potom ve transakci zapsat data a nastavit na SET todo=False + v mém případě ještě SET when=now() což je čas počátku transakce. Takže pochopitelně si pohlídat fci, jestli je to čas transakce nebo počátku session. Já to měl vlastně stejné, každý klient se připojil, zpracoval jeden záznam (až minuty nebo desítky minut), nebylo možné blokovat ostatní klienty (miliony položek v todo), takže jsem to vyřešit takto a doma v home labu jsem takto pustil jednoho klienta per CPU Thread, takže na síti cca 128 workerů a každý jeden řešil jeden obrázek (v mém případě, render z POVRay, převod na png správných rozměrů a ořezů a nakonec vytvoření animace a export jako video). Na data má Postgresql datový typ BYTEA do 1GB, což se vešlo.
Takže ověřit si, jestli MySQL umí serializable, jestli umí atomický set a where (ano umí, ale je potřeba si to vyžádat správnou izolací) a lze to mít i bez transakční izolace serializable, která toho uzamyká no vlastně všechno.
Tomáš Vondra o tom napsal pěkný článek na 2quadrant, ale nemůžu to najít.