sql >> Base de Datos >  >> RDS >> Sqlserver

¿Por qué insertar un bloque de declaraciones TSQL cuando el nivel de aislamiento de transacción para otra transacción es serializable con un filtro sin conflictos?

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')