Bien que la réponse ci-dessus soit vraie en ce sens qu'un SELECT ... FOR UPDATE empêchera les sessions/transactions simultanées d'insérer le même enregistrement, ce n'est pas toute la vérité. Je me bats actuellement avec le même problème et je suis arrivé à la conclusion que le SELECT ... FOR UPDATE est presque inutile dans cette situation pour la raison suivante :
Une transaction / session simultanée peut également effectuer un SELECT ... FOR UPDATE sur la même valeur d'enregistrement / d'index, et MySQL acceptera volontiers cela immédiatement (non bloquant) et sans générer d'erreurs. Bien sûr, dès que l'autre session a fait cela, votre session non plus ne peut plus insérer l'enregistrement. Ni votre ni l'autre session / transaction n'obtiennent d'informations sur la situation et pensent qu'ils peuvent insérer l'enregistrement en toute sécurité jusqu'à ce qu'ils essaient réellement de le faire. Essayer d'insérer alors conduit soit à un blocage, soit à une erreur de clé en double, selon les circonstances.
En d'autres termes, SELECT ... FOR UPDATE empêche les autres sessions d'insérer le ou les enregistrements respectifs, MAIS même si vous faites un SELECT ... FOR UPDATE et que l'enregistrement respectif n'est pas trouvé, il est probable que vous ne puissiez pas réellement insérer cet enregistrement. À mon humble avis, cela rend inutile la méthode "première requête, puis insertion".
La cause du problème est que MySQL n'offre aucune méthode pour vraiment verrouiller les enregistrements inexistants. Deux sessions / transactions simultanées peuvent verrouiller des enregistrements inexistants "FOR UPDATE" en même temps, ce qui ne devrait vraiment pas être possible et qui rend le développement beaucoup plus difficile.
La seule façon de contourner ce problème semble être d'utiliser des tables de sémaphores ou de verrouiller toute la table lors de l'insertion. Veuillez vous référer à la documentation MySQL pour plus de détails sur le verrouillage de tables entières ou l'utilisation de tables de sémaphores.
Juste mes 2 centimes...