Ada beberapa skenario yang mungkin mudah dipecahkan, dan yang buruk tidak.
Untuk pengguna yang memasukkan nilai, kemudian masukkan nilai yang sama beberapa waktu kemudian SELECT sederhana sebelum INSERT akan mendeteksi masalah. Ini berfungsi untuk kasus di mana satu pengguna mengirimkan nilai dan beberapa waktu kemudian pengguna lain mengirimkan nilai yang sama.
Jika pengguna mengirimkan daftar nilai dengan duplikat - katakan {ABC, DEF, ABC} - dalam satu permintaan tunggal dari kode aplikasi dapat mendeteksi dan memfilter duplikat, mungkin melemparkan kesalahan. Anda juga perlu memeriksa bahwa DB tidak mengandung nilai unik apa pun sebelum disisipkan.
Skenario yang rumit adalah ketika menulis satu pengguna di dalam DBMS pada saat yang sama dengan menulis pengguna lain, dan mereka menulis nilai yang sama. Maka Anda memiliki ras kondisi di antara mereka. Karena DBMS (kemungkinan besar - Anda tidak mengatakan yang mana yang Anda gunakan) sistem multitasking preemptive tugas apa pun dapat dijeda pada setiap saat dalam pelaksanaannya. Itu berarti tugas pengguna1 dapat memeriksa tidak ada baris yang ada, maka tugas pengguna2 dapat memeriksa tidak ada baris yang ada, maka tugas pengguna1 dapat menyisipkan baris itu, maka tugas pengguna2 dapat memasukkan baris itu. Pada setiap titik, tugas-tugas secara individual bahagia karena mereka melakukan hal yang benar. Namun, secara global terjadi kesalahan.
Biasanya DBMS akan menangani ini dengan mengunci nilai yang dimaksud. Dalam masalah ini Anda membuat baris baru sehingga tidak ada apa pun untuk dikunci. Jawabannya adalah kunci rentang. Seperti yang disarankan ini mengunci berbagai nilai, apakah mereka saat ini ada atau tidak. Setelah dikunci rentang itu tidak dapat diakses oleh tugas lain sampai kunci dilepaskan. Untuk mendapatkan kunci rentang, Anda harus menentukan dan tingkat isolasi SERIALIZABLE . Fenomena tugas lain menyelinap berturut-turut setelah tugas Anda diperiksa dikenal sebagai catatan hantu .
Mengatur level isolasi ke Serializable di seluruh aplikasi akan memiliki implikasi. Throughput akan berkurang. Kondisi balapan lain yang bekerja cukup baik di masa lalu mungkin mulai menunjukkan kesalahan sekarang. Saya akan menyarankan pengaturan pada koneksi yang mengeksekusi duplikat-kode yang menyebabkan Anda dan meninggalkan sisa aplikasi apa adanya.
Alternatif berbasis kode adalah memeriksa setelah penulisan daripada sebelumnya. Jadi lakukan INSERT, lalu hitung jumlah baris yang memiliki nilai hash. Jika ada duplikat kembalikan tindakan. Ini dapat memiliki beberapa hasil buruk. Katakan tugas 1 tulis lalu tugas 2. Lalu tugas 1 memeriksa dan menemukan duplikat. Itu berputar kembali meskipun itu yang pertama. Demikian pula kedua tugas dapat mendeteksi duplikat dan keduanya rollback. Tetapi setidaknya Anda akan memiliki pesan untuk dikerjakan, mekanisme coba lagi dan tidak ada duplikat baru. Rollback disukai, seperti menggunakan pengecualian untuk mengontrol aliran program. Perhatikan baik-baik itu semuapekerjaan dalam transaksi akan dibatalkan, bukan hanya penulisan duplikat. Dan Anda harus memiliki transaksi eksplisit yang dapat mengurangi konkurensi. Pemeriksaan duplikat akan sangat lambat kecuali Anda memiliki indeks pada hash. Jika Anda melakukannya, Anda bisa membuatnya menjadi unik!
Seperti yang Anda komentari, solusi nyata adalah indeks unik. Menurut saya ini harus sesuai dengan jendela perawatan Anda (meskipun tentu saja Anda tahu sistem Anda yang terbaik). Katakanlah hash adalah delapan byte. Untuk seratus juta baris itu sekitar 1GB. Pengalaman menunjukkan sedikit perangkat keras yang masuk akal akan memproses banyak baris ini dalam satu atau dua menit, puncak. Pemeriksaan dan penghapusan duplikat akan menambah ini, tetapi dapat ditulis terlebih dahulu. Ini hanya samping.