Masalah pertama dalam skenario pengujian Anda adalah bahwa tabel tidak memiliki indeks yang berguna pada firstname
. Yang kedua adalah mejanya kosong.
Dari Penguncian Rentang Kunci dalam BOL
Tidak ada indeks yang cocok untuk mengambil RangeS-S
mengunci sehingga untuk menjamin semantik serial, SQL Server perlu mengunci seluruh tabel.
Jika Anda mencoba menambahkan indeks berkerumun pada tabel di kolom nama depan seperti di bawah ini dan ulangi percobaan ...
CREATE CLUSTERED INDEX [IX_FirstName] ON [dbo].[dummy] ([firstname] ASC)
... Anda akan menemukan bahwa Anda masih diblokir!
Terlepas dari kenyataan bahwa indeks yang sesuai sekarang ada dan rencana eksekusi menunjukkan bahwa indeks tersebut dicari untuk memenuhi kueri.
Anda dapat mengetahui alasannya dengan menjalankan yang berikut
SET TRANSACTION ISOLATION LEVEL SERIALIZABLE
BEGIN TRAN
SELECT *
FROM dummy
WHERE firstname = 'abc'
SELECT resource_type,
resource_description,
request_mode
FROM sys.dm_tran_locks
WHERE request_session_id = @@SPID
COMMIT
Kembali
+---------------+----------------------+--------------+
| resource_type | resource_description | request_mode |
+---------------+----------------------+--------------+
| DATABASE | | S |
| OBJECT | | IS |
| PAGE | 1:198 | IS |
| KEY | (ffffffffffff) | RangeS-S |
+---------------+----------------------+--------------+
SQL Server tidak hanya mengeluarkan kunci rentang tepat pada rentang yang Anda tentukan dalam kueri Anda.
Untuk predikat kesetaraan pada indeks unik jika ada kunci yang cocok, itu hanya akan mengambil kunci biasa daripada semua jenis kunci rentang sama sekali.
Untuk predikat pencarian yang tidak unik, ia mengeluarkan kunci pada semua kunci yang cocok dalam rentang ditambah yang "berikutnya" di akhir rentang (atau pada ffffffffffff
untuk mewakili tak terhingga jika tidak ada kunci "berikutnya"). Bahkan catatan "hantu" yang dihapus
dapat digunakan dalam penguncian tombol rentang ini.
Seperti yang dijelaskan di sini untuk predikat kesetaraan pada indeks unik atau tidak unik
Jadi dengan tabel kosong SELECT
masih berakhir mengunci seluruh indeks. Anda juga harus menyisipkan baris sebelumnya di antara abc
dan lmn
dan kemudian penyisipan Anda akan berhasil.
insert into dummy values('def', 'def')