Il primo problema nello scenario di test è che la tabella non ha un indice utile su firstname
. La seconda è che il tavolo è vuoto.
Da Blocco dell'intervallo di chiavi in BOL
Non esiste un indice adatto per prendere RangeS-S
si blocca in modo da garantire una semantica serializzabile SQL Server deve bloccare l'intera tabella.
Se provi ad aggiungere un indice cluster sulla tabella nella colonna del nome come di seguito e ripeti l'esperimento...
CREATE CLUSTERED INDEX [IX_FirstName] ON [dbo].[dummy] ([firstname] ASC)
... scoprirai di essere ancora bloccato!
Nonostante il fatto che ora esista un indice adatto e il piano di esecuzione mostri che viene cercato per soddisfare la query.
Puoi capire perché eseguendo quanto segue
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
Resi
+---------------+----------------------+--------------+
| resource_type | resource_description | request_mode |
+---------------+----------------------+--------------+
| DATABASE | | S |
| OBJECT | | IS |
| PAGE | 1:198 | IS |
| KEY | (ffffffffffff) | RangeS-S |
+---------------+----------------------+--------------+
SQL Server non si limita a eliminare un blocco di intervallo esattamente sull'intervallo specificato nella query.
Per un predicato di uguaglianza su un indice univoco, se esiste una chiave corrispondente, richiederà semplicemente un blocco normale anziché qualsiasi tipo di blocco dell'intervallo.
Per un predicato di ricerca non univoco rimuove i blocchi su tutte le chiavi corrispondenti all'interno dell'intervallo più quella "successiva" alla fine dell'intervallo (o su ffffffffffff
per rappresentare l'infinito se non esiste una chiave "successivo"). Anche i record "ghost" eliminati
può essere utilizzato in questa gamma di chiusura a chiave.
Come descritto qui per un predicato di uguaglianza su un indice univoco o non univoco
Quindi con una tabella vuota il SELECT
finisce comunque per bloccare l'intero indice. Dovresti anche aver precedentemente inserito una riga tra abc
e lmn
e poi il tuo inserimento avrà successo.
insert into dummy values('def', 'def')