上記の答えは SELECT ... FOR UPDATE が同時セッション/トランザクションが同じレコードを挿入するのを防ぐという点で真実ですが、それは完全な真実ではありません。私は現在同じ問題に取り組んでおり、次の理由により、その状況では SELECT ... FOR UPDATE はほとんど役に立たないという結論に達しました。
並行トランザクション/セッションは、まったく同じレコード/インデックス値に対して SELECT ... FOR UPDATE を実行することもでき、MySQL はエラーをスローすることなく、すぐに (非ブロッキングで) 喜んでそれを受け入れます。もちろん、他のセッションがそれを行うとすぐに、あなたのセッションもレコードを挿入できなくなります。あなたも他のセッション/トランザクションも、状況に関する情報を取得せず、実際に挿入しようとするまで、レコードを安全に挿入できると考えています。次に挿入しようとすると、状況に応じて、デッドロックまたは重複キー エラーが発生します。
つまり、SELECT ... FOR UPDATE は、他のセッションがそれぞれのレコードを挿入するのを防ぎますが、SELECT ... FOR UPDATE を実行してそれぞれのレコードが見つからない場合でも、実際にはできない可能性があります。そのレコードを挿入します。私見、それは「最初のクエリ、次に挿入」メソッドを役に立たなくします。
この問題の原因は、MySQL が存在しないレコードを実際にロックする方法を提供していないことです。2 つの同時セッション/トランザクションは、存在しないレコードを同時に "FOR UPDATE" でロックできます。これは実際には不可能であり、開発を大幅に困難にします。
これを回避する唯一の方法は、セマフォ テーブルを使用するか、挿入時にテーブル全体をロックすることです。テーブル全体のロックまたはセマフォ テーブルの使用の詳細については、MySQL のドキュメントを参照してください。
ちょうど私の2セント...