¿El nivel de aislamiento serializable de SQL Server bloquea toda la tabla

9

Yo y un colega mío discutimos las implicaciones del uso del nivel de aislamiento serializable. Dijo que bloqueaba toda la mesa, pero no estaba de acuerdo con eso diciéndole que podría hacerlo, pero intenta aplicar bloqueos de rango y no aplica la verdadera serialización como se explica aquí: El nivel de aislamiento serializable .

Tampoco puedo encontrar nada en los documentos para "bloquea toda la tabla": ESTABLECER NIVEL DE AISLAMIENTO DE TRANSACCIÓN .

El documento establece un montón de cosas con respecto a los bloqueos de rango, por lo que, en teoría, podría bloquear toda la tabla simplemente con un bloqueo de rango que bloquee todo el rango de valores posibles en la tabla, pero no bloquea la tabla.

¿Estoy completamente equivocado aquí? ¿De hecho bloquea toda la mesa (o tablas)?

mslot
fuente

Respuestas:

16

Aunque la escalada

La escalada de bloqueo bajo un nivel de aislamiento serializable puede ocurrir de la misma manera que ocurre con otros niveles de aislamiento.

  • Los índices correctos pueden ayudar a evitar la escalada de bloqueo hasta cierto punto
  • El bloqueo de muchos índices aumentará la probabilidad de una escalada de bloqueo; el recuento es acumulativo entre objetos para una sola declaración

Algunos ejemplos rápidos que usan una sola tabla con un solo índice. Id es la clave principal y el índice agrupado en la tabla.

Una fila

SET TRANSACTION ISOLATION LEVEL SERIALIZABLE
BEGIN TRAN

UPDATE c
SET c.Score = 2147483647 
FROM dbo.Comments AS c
WHERE c.Id = 138; --One value

ROLLBACK

Para un solo valor de Id, el bloqueo es mínimo.

+--------------+---------------+---------------+-------------+
| request_mode | locked_object | resource_type | total_locks |
+--------------+---------------+---------------+-------------+
| RangeX-X     | Comments      | KEY           |           1 |
| IX           | Comments      | OBJECT        |           1 |
| IX           | Comments      | PAGE          |           1 |
+--------------+---------------+---------------+-------------+

Filas múltiples

Pero las cerraduras subirán si comenzamos a trabajar en rangos:

SET TRANSACTION ISOLATION LEVEL SERIALIZABLE
BEGIN TRAN

UPDATE c
SET c.Score = 2147483647 
FROM dbo.Comments AS c
WHERE c.Id BETWEEN 1 AND 5000; -- Small range

ROLLBACK

Ahora tenemos cerraduras más exclusivas en más llaves:

+--------------+---------------+---------------+-------------+
| request_mode | locked_object | resource_type | total_locks |
+--------------+---------------+---------------+-------------+
| RangeX-X     | Comments      | KEY           |        2429 |
| IX           | Comments      | OBJECT        |           1 |
| IX           | Comments      | PAGE          |          97 |
+--------------+---------------+---------------+-------------+

Mucho más filas

Esto continuará hasta que alcancemos un punto de inflexión:

SET TRANSACTION ISOLATION LEVEL SERIALIZABLE
BEGIN TRAN

UPDATE c
SET c.Score = 2147483647 
FROM dbo.Comments AS c
WHERE c.Id BETWEEN 1 AND 11655; --Larger range

ROLLBACK

Se intenta la escalada de bloqueo y se realiza correctamente:

+--------------+---------------+---------------+-------------+
| request_mode | locked_object | resource_type | total_locks |
+--------------+---------------+---------------+-------------+
| X            | Comments      | OBJECT        |           1 |
+--------------+---------------+---------------+-------------+

Presta atención

Es importante separar dos conceptos aquí: el nivel de aislamiento será serializable sin importar qué tipo de bloqueos se tomen. La consulta elige el nivel de aislamiento y el motor de almacenamiento elige los bloqueos. Serializable no siempre dará como resultado bloqueos de rango: el motor de almacenamiento puede elegir cualquier tipo de bloqueos que aún respeten el nivel de aislamiento.

Erik Darling
fuente
5

Si hay un índice en un predicado de búsqueda, podría usarse para bloqueos de rango .

Es decir, bloquear de la primera fila a la siguiente en el rango. Y desde el siguiente hasta la tercera fila, etc. Hasta la última fila del rango. Esencialmente, una serie de bloqueos de fila, pero bloquea el rango de las inserciones también para valores "intermedios" (bloqueo del rango).

Para que esto suceda, usted (SQL Server) necesita tener un índice para trabajar. Sin índices para bloquear (índices en predicados), obtendrá (por lo que sé) obtendrá bloqueos de tabla.

Tibor Karaszi
fuente