El primer problema en su escenario de prueba es que la tabla no tiene un índice útil en firstname
. La segunda es que la mesa está vacía.
Desde Bloqueo de intervalo de teclas en BOL
No existe un índice adecuado para tomar RangeS-S
se bloquea para garantizar la semántica serializable que SQL Server necesita para bloquear toda la tabla.
Si intenta agregar un índice agrupado en la tabla en la columna de nombre como se muestra a continuación y repite el experimento...
CREATE CLUSTERED INDEX [IX_FirstName] ON [dbo].[dummy] ([firstname] ASC)
... encontrará que todavía está bloqueado!
A pesar de que ahora existe un índice adecuado y el plan de ejecución muestra que se busca para satisfacer la consulta.
Puede ver por qué ejecutando lo siguiente
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
Devoluciones
+---------------+----------------------+--------------+
| resource_type | resource_description | request_mode |
+---------------+----------------------+--------------+
| DATABASE | | S |
| OBJECT | | IS |
| PAGE | 1:198 | IS |
| KEY | (ffffffffffff) | RangeS-S |
+---------------+----------------------+--------------+
SQL Server no solo elimina un bloqueo de rango exactamente en el rango que especifica en su consulta.
Para un predicado de igualdad en un índice único, si hay una clave coincidente, solo se necesitará un bloqueo normal en lugar de cualquier tipo de bloqueo de rango.
Para un predicado de búsqueda no único, elimina bloqueos en todas las claves coincidentes dentro del rango más la "siguiente" al final del rango (o en ffffffffffff
para representar el infinito si no existe ninguna tecla "siguiente"). Incluso registros "fantasma" eliminados
se puede utilizar en este rango de bloqueo de teclas.
Como se describe aquí para un predicado de igualdad en un índice único o no único
Entonces, con una tabla vacía, SELECT
todavía termina bloqueando todo el índice. También tendría que haber insertado previamente una fila entre abc
y lmn
y luego su inserción tendría éxito.
insert into dummy values('def', 'def')