Zatímco výše uvedená odpověď je pravdivá v tom, že SELECT ... FOR UPDATE zabrání souběžným relacím / transakcím ve vkládání stejného záznamu, není to úplná pravda. Momentálně bojuji se stejným problémem a dospěl jsem k závěru, že SELECT ... FOR UPDATE je v této situaci téměř k ničemu z následujícího důvodu:
Souběžná transakce / relace může také provést SELECT ... FOR UPDATE na stejné hodnotě záznamu / indexu a MySQL to ochotně přijme okamžitě (neblokuje) a bez vyvolání chyb. Samozřejmě, jakmile to udělá druhá relace, ani vaše relace již nemůže vložit záznam. Ani vaše ani jiná relace / transakce nezískají žádné informace o situaci a myslí si, že mohou bezpečně vložit záznam, dokud se o to skutečně nepokusí. Pokus o vložení pak vede buď k uváznutí, nebo k chybě duplicitního klíče, v závislosti na okolnostech.
Jinými slovy, SELECT ... FOR UPDATE zabrání jiným relacím vložit příslušný záznam (záznamy), ALE i když provedete SELECT ... FOR UPDATE a příslušný záznam nebude nalezen, je pravděpodobné, že ve skutečnosti nemůžete vložte ten záznam. IMHO to dělá metodu "nejdříve dotaz, pak vlož" zbytečnou.
Příčinou problému je, že MySQL nenabízí žádnou metodu, jak skutečně uzamknout neexistující záznamy. Dvě souběžné relace / transakce mohou současně uzamknout neexistující záznamy "PRO AKTUALIZACI", což by ve skutečnosti nemělo být možné a výrazně to ztěžuje vývoj.
Zdá se, že jediným způsobem, jak to obejít, je použití semaforových tabulek nebo uzamčení celé tabulky při vkládání. Další informace o zamykání celých tabulek nebo používání semaforových tabulek naleznete v dokumentaci k MySQL.
Jen moje 2 centy ...