Katakanlah Anda memiliki kode berikut (abaikan saja itu buruk):
BEGIN TRAN;
DECLARE @id int
SELECT @id = id + 1 FROM TableA;
UPDATE TableA SET id = @id; --TableA must have only one row, apparently!
COMMIT TRAN;
-- @id is returned to the client or used somewhere else
Bagi saya, ini BUKAN mengelola konkurensi dengan benar. Hanya karena Anda melakukan transaksi tidak berarti orang lain tidak akan membaca nilai yang sama dengan yang Anda lakukan sebelum Anda mendapatkan pernyataan pembaruan Anda.
Sekarang, biarkan kode apa adanya (saya menyadari ini lebih baik ditangani sebagai satu pernyataan atau bahkan lebih baik menggunakan kolom autoincrement / identitas) apa cara yang pasti untuk membuatnya menangani konkurensi dengan benar dan mencegah kondisi balapan yang memungkinkan dua klien untuk mendapatkan yang sama nilai id?
Saya cukup yakin bahwa menambahkan WITH (UPDLOCK, HOLDLOCK)
ke SELECT akan melakukan trik. The tingkat isolasi transaksi Serializable akan tampaknya bekerja juga karena itu menyangkal orang lain untuk membaca apa yang Anda lakukan sampai tran berakhir ( UPDATE :. Ini salah See Martin jawaban). Benarkah? Apakah keduanya akan bekerja dengan baik? Apakah yang satu lebih disukai daripada yang lain?
Bayangkan melakukan sesuatu yang lebih sah daripada pembaruan ID - beberapa perhitungan berdasarkan pembacaan yang perlu Anda perbarui. Mungkin ada banyak tabel yang terlibat, beberapa di antaranya akan Anda tulis dan yang lain tidak. Apa praktik terbaik di sini?
Setelah menulis pertanyaan ini, saya pikir petunjuk kunci lebih baik karena Anda hanya mengunci tabel yang Anda butuhkan, tapi saya menghargai masukan siapa pun.
PS Dan tidak, saya tidak tahu jawaban terbaik dan benar-benar ingin mendapatkan pemahaman yang lebih baik! :)
update
yang mungkin didasarkan pada data yang sudah usang? Jika yang terakhir, Anda dapat menggunakanrowversion
kolom untuk memeriksa apakah baris yang akan diperbarui belum diubah sejak dibaca.