Sementara jawaban di atas benar bahwa SELECT ... FOR UPDATE akan mencegah sesi/transaksi bersamaan memasukkan catatan yang sama, itu tidak sepenuhnya benar. Saat ini saya berjuang dengan masalah yang sama dan sampai pada kesimpulan bahwa SELECT ... FOR UPDATE hampir tidak berguna dalam situasi itu karena alasan berikut:
Transaksi / sesi bersamaan juga dapat melakukan SELECT ... FOR UPDATE pada catatan / nilai indeks yang sama, dan MySQL akan dengan senang hati menerimanya segera (non-blocking) dan tanpa membuang kesalahan. Tentu saja, segera setelah sesi lain melakukannya, sesi Anda juga tidak dapat memasukkan catatan lagi. Baik sesi/transaksi Anda maupun sesi/transaksi lainnya tidak mendapatkan informasi tentang situasi tersebut dan berpikir mereka dapat dengan aman memasukkan catatan sampai mereka benar-benar mencoba melakukannya. Mencoba menyisipkan akan menyebabkan kebuntuan atau kesalahan kunci duplikat, tergantung pada keadaan.
Dengan kata lain, SELECT ... FOR UPDATE mencegah sesi lain memasukkan catatan masing-masing, TETAPI bahkan jika Anda melakukan SELECT ... FOR UPDATE dan catatan masing-masing tidak ditemukan, kemungkinan Anda tidak dapat benar-benar masukkan catatan itu. IMHO, yang membuat metode "permintaan pertama, lalu masukkan" tidak berguna.
Penyebab masalahnya adalah MySQL tidak menawarkan metode apa pun untuk benar-benar mengunci catatan yang tidak ada. Dua sesi/transaksi bersamaan dapat mengunci catatan yang tidak ada "UNTUK PEMBARUAN" pada saat yang sama, suatu hal yang seharusnya tidak mungkin dilakukan dan yang membuat pengembangan menjadi lebih sulit secara signifikan.
Satu-satunya cara untuk mengatasi ini tampaknya menggunakan tabel semaphore atau mengunci seluruh tabel saat memasukkan. Silakan merujuk ke dokumentasi MySQL untuk referensi lebih lanjut tentang mengunci seluruh tabel atau menggunakan tabel semaphore.
Hanya 2 sen saya ...