Anda perlu melakukan ini dalam transaksi untuk memastikan dua klien simultan tidak akan memasukkan fieldValue yang sama dua kali:
SET TRANSACTION ISOLATION LEVEL SERIALIZABLE
BEGIN TRANSACTION
DECLARE @id AS INT
SELECT @id = tableId FROM table WHERE [email protected]
IF @id IS NULL
BEGIN
INSERT INTO table (fieldValue) VALUES (@newValue)
SELECT @id = SCOPE_IDENTITY()
END
SELECT @id
COMMIT TRANSACTION
Anda juga dapat menggunakan Penguncian dengan pemeriksaan ganda untuk mengurangi overhead penguncian
DECLARE @id AS INT
SELECT @id = tableID FROM table (NOLOCK) WHERE [email protected]
IF @id IS NULL
BEGIN
SET TRANSACTION ISOLATION LEVEL SERIALIZABLE
BEGIN TRANSACTION
SELECT @id = tableID FROM table WHERE [email protected]
IF @id IS NULL
BEGIN
INSERT INTO table (fieldValue) VALUES (@newValue)
SELECT @id = SCOPE_IDENTITY()
END
COMMIT TRANSACTION
END
SELECT @id
Adapun mengapa ISOLATION LEVEL SERIALIZABLE diperlukan, ketika Anda berada di dalam transaksi serializable, SELECT pertama yang menyentuh tabel membuat kunci rentang yang mencakup tempat di mana catatan seharusnya berada, jadi tidak ada orang lain yang dapat memasukkan catatan yang sama sampai transaksi ini berakhir.
Tanpa ISOLATION LEVEL SERIALIZABLE, tingkat isolasi default (READ COMMITTED) tidak akan mengunci tabel pada waktu baca, jadi antara SELECT dan UPDATE, seseorang masih dapat menyisipkan. Transaksi dengan tingkat isolasi READ COMMITTED tidak menyebabkan SELECT terkunci. Transaksi dengan REPEATABLE READS mengunci catatan (jika ditemukan) tetapi bukan celahnya.