Bloquear intervalos con clave

Los bloqueos de intervalos con clave protegen un intervalo de filas incluido implícitamente en un conjunto de registros que se lee con una instrucción Transact-SQL mientras se utiliza el nivel de aislamiento de transacción serializable. El nivel de aislamiento serializable requiere que las consultas ejecutadas durante una transacción deben obtener el mismo conjunto de filas cada vez que se ejecutan en la transacción. El bloqueo de intervalos con clave protege este requisito, ya que impide que otras transacciones inserten nuevas filas cuyas claves se incluirían en el intervalo de claves leído por la transacción serializable.

El bloqueo de intervalos con clave impide las lecturas ficticias. La protección de los intervalos de claves entre filas también impide las inserciones ficticias en un conjunto de registros a los que tiene acceso una transacción.

El bloqueo de intervalos con clave se incluye en un índice, especificando los valores de clave inicial y final. Este bloqueo impide la inserción, actualización o eliminación de filas con un valor de clave incluido en el intervalo, ya que estas operaciones deben obtener en primer lugar un bloqueo en el índice. Por ejemplo, una transacción serializable podría emitir una instrucción SELECT que lee todas las filas cuyos valores clave se encuentran entre 'AAA' y 'CZZ'. El bloqueo de intervalos con clave en los valores de clave del intervalo 'AAA' a 'CZZ' impide que otras transacciones inserten filas con valores de clave situados en dicho intervalo, como 'ADG', 'BBD' o 'CAL'.

Modos de bloqueo de intervalos con clave

Los bloqueos de intervalos con clave incluyen dos componentes, una fila y un intervalo, especificados con el formato intervalo-fila:

  • El intervalo representa el modo de bloqueo que protege el intervalo entre dos entradas de índice consecutivas.

  • La fila representa el modo de bloqueo que protege la entrada de índice.

  • El modo representa el modo de bloqueo combinado que se utiliza. Los modos de bloqueo del intervalo de claves constan de dos partes. La primera representa el tipo de bloqueo que se utiliza para bloquear el intervalo del índice (RangeT) y la segunda representa el tipo de bloqueo que se utiliza para bloquear una clave específica (K). Ambas partes se conectan con un guión (-), como RangeT-K.

    Intervalo

    Fila

    Modo

    Descripción

    RangeS

    S

    RangeS-S

    Intervalo compartido, bloqueo de recurso compartido; recorrido de intervalo serializable.

    RangeS

    U

    RangeS-U

    Intervalo compartido, bloqueo de recurso de actualización; recorrido de actualización serializable.

    RangeI

    NULL

    RangeI-N

    Intervalo de inserción, bloqueo de recurso nulo; se utiliza para comprobar los intervalos antes de insertar una nueva clave en un índice.

    RangeX

    X

    RangeX-X

    Intervalo exclusivo, bloqueo de recurso exclusivo; se utiliza al actualizar una clave de un intervalo.

Nota

El modo de bloqueo Null interno es compatible con los demás modos de bloqueo.

Los modos de bloqueo de intervalos con clave tienen una matriz de compatibilidad que muestra los bloqueos que son compatibles con otros bloqueos obtenidos en claves e intervalos superpuestos. Para consultar la matriz completa de compatibilidad de bloqueos, vea Compatibilidad de bloqueos.

 

Modo concedido existente

 

 

 

 

 

 

Modo solicitado

S

U

X

RangeS-S

RangeS-U

RangeI-N

RangeX-X

Compartido (S)

No

No

Actualizar (U)

No

No

No

No

Exclusivo (X)

No

No

No

No

No

No

RangeS-S

No

No

No

RangeS-U

No

No

No

No

No

RangeI-N

No

No

No

RangeX-X

No

No

No

No

No

No

No

Bloqueos de conversión

Los bloqueos de conversión se crean cuando un bloqueo de intervalos con clave se superpone a otro bloqueo.

Bloqueo 1

Bloqueo 2

Bloqueo de conversión

S

RangeI-N

RangeI-S

U

RangeI-N

RangeI-U

X

RangeI-N

RangeI-X

RangeI-N

RangeS-S

RangeX-S

RangeI-N

RangeS-U

RangeX-U

Los bloqueos de conversión se producen durante breves períodos de tiempo en circunstancias diversas y complejas, y en ocasiones mientras se ejecutan procesos simultáneos.

Recorrido de intervalo serializable, recuperación de singleton, eliminación e inserción

El bloqueo de intervalos con clave garantiza que las siguientes operaciones son serializables:

  • Consulta de recorrido de intervalos

  • Recuperación de singleton de fila inexistente

  • Operación de eliminación

  • Operación de inserción

Para que el bloqueo de intervalos con clave se produzca, es necesario que se cumplan las condiciones siguientes:

  • El nivel de aislamiento de las transacciones se debe establecer en SERIALIZABLE.

  • El procesador de consultas debe utilizar un índice para implementar el predicado del filtro de intervalo. Por ejemplo, la cláusula WHERE de una instrucción SELECT puede establecer una condición de intervalo con este predicado: ColumnX BETWEEN N**'AAA'** AND N**'CZZ'**. El bloqueo de intervalos con clave sólo se puede adquirir si una clave de índice abarca la ColumnX.

Ejemplos

La tabla y el índice siguientes se utilizan como base para los ejemplos de bloqueo de intervalos con clave que se muestran a continuación.

Ilustración de tabla de base de datos con árbol b del índice

Consulta de recorrido de intervalos

Para poder asegurar que una consulta de recorrido de intervalos es serializable, la misma consulta debe devolver los mismos resultados cada vez que se ejecuta en la misma transacción. Otras transacciones no deben insertar nuevas filas en la consulta de recorrido de intervalos; de lo contrario, se convierten en inserciones ficticias. Por ejemplo, la siguiente consulta utiliza la tabla y el índice de la ilustración anterior:

SELECT name
    FROM mytable
    WHERE name BETWEEN 'A' AND 'C';

Los bloqueos de intervalos con clave se colocan en las entradas de índice que corresponden al intervalo de filas de datos cuyo nombre se encuentra entre los valores Adam y Dale, impidiendo así que se agreguen o eliminen nuevas filas obtenidas en la consulta anterior. Aunque el primer nombre del intervalo es Adam, el bloqueo de intervalos con clave RangeS-S en esta entrada de índice garantiza que no se pueden agregar nombres nuevos que empiecen por la letra A delante de Adam, como Abigail. De forma similar, el bloqueo de intervalos con clave RangeS-S en la entrada de índice de Dale garantiza que no se van a agregar nombres nuevos que empiecen por la letra C detrás de Carlos, como Clive.

Nota

El número de bloqueos RangeS-S que se mantiene es n+1, siendo n el número de filas que satisfacen la consulta.

Recuperación de singleton de datos inexistentes

Si una consulta de una transacción intenta seleccionar una fila que no existe, la ejecución de la consulta en un punto posterior de la misma transacción tiene que devolver el mismo resultado. No se puede permitir a otra transacción insertar la fila inexistente. Por ejemplo, con esta consulta:

SELECT name
    FROM mytable
    WHERE name = 'Bill';

Se aplica un bloqueo de intervalos con clave a la entrada de índice correspondiente al intervalo de nombres comprendido entre Ben y Bing, ya que se podría insertar el nombre Bill entre estas dos entradas de índice adyacentes. El bloqueo de intervalos con clave del modo RangeS-S se coloca en la entrada de índice Bing. Esto impide que otra transacción inserte valores, como Bill, entre las entradas de índice Ben y Bing.

Operación de eliminación

Cuando se elimina un valor en una transacción, el intervalo en el que entra el valor no debe estar bloqueado mientras se ejecuta la transacción que realiza la operación de eliminación. Para mantener la seriabilidad basta con bloquear el valor de la clave eliminada hasta el final de la transacción. Por ejemplo, con esta instrucción DELETE:

DELETE mytable
    WHERE name = 'Bob';

Se ha colocado un bloqueo exclusivo (X) en la entrada de índice correspondiente al nombre Bob. Otras transacciones pueden insertar o eliminar valores antes o después del valor eliminado Bob. Sin embargo, cualquier transacción que intente leer, insertar o eliminar el valor Bob se bloqueará hasta que la transacción de eliminación se confirme o se revierta.

La eliminación del intervalo se puede ejecutar con tres modos de bloqueo básicos: bloqueo de fila, de página o de tabla. El optimizador de consultas decide la estrategia de bloqueo de página, tabla o fila, o bien la especifica el usuario mediante sugerencias del optimizador como ROWLOCK, PAGLOCK o TABLOCK. Cuando se utiliza PAGLOCK o TABLOCK, Motor de base de datos anula de forma inmediata la asignación de una página de índice si se eliminan todas sus filas. Por el contrario, cuando se utiliza ROWLOCK, todas las filas eliminadas se marcan sólo como eliminadas, y se quitan de la página de índice posteriormente mediante una tarea en segundo plano.

Operación de inserción

Cuando se inserta un valor en una transacción, el intervalo en el que entra el valor no debe estar bloqueado mientras se ejecuta la transacción que realiza la operación de inserción. Basta con bloquear el valor de clave insertado hasta el final de la transacción para mantener la seriabilidad. Por ejemplo, con esta instrucción INSERT:

INSERT mytable VALUES ('Dan');

El bloqueo de intervalos con clave de modo RangeI-N se coloca en la entrada de índice correspondiente al nombre David para probar el intervalo. Si se concede el bloqueo, se inserta Dan y se coloca un bloqueo exclusivo (X) en el valor Dan. El bloqueo de intervalos con clave de modo RangeI-N sólo es necesario para probar el intervalo y no se mantiene mientras se ejecuta la transacción que realiza la operación de inserción. Otras transacciones pueden insertar o eliminar valores antes o después del valor insertado Dan. Sin embargo, cualquier transacción que intente leer, insertar o eliminar el valor Dan se bloqueará hasta que se confirme o se revierta la transacción de inserción.