Compartir a través de


Directrices sobre los niveles de aislamiento de transacciones con tablas Memory-Optimized

En muchos escenarios, debe especificar el nivel de aislamiento de transacción. El aislamiento de transacciones para tablas optimizadas para memoria difiere de las tablas basadas en disco.

Requisitos para especificar el nivel de aislamiento de transacción:

  • TRANSACTION ISOLATION LEVEL es una opción necesaria para el bloque ATOMIC que comprende el contenido de un procedimiento almacenado que se compila de forma nativa.

  • Debido a las restricciones en el uso del nivel de aislamiento en transacciones entre contenedores, el uso de tablas optimizadas para memoria en interpretaciones de Transact-SQL a menudo debe ir acompañado de una indicación de tabla que especifique el nivel de aislamiento utilizado para acceder a la tabla. Para obtener más información sobre las sugerencias de nivel de aislamiento y las transacciones entre contenedores, consulte Niveles de aislamiento de transacciones.

  • El nivel de aislamiento de transacción deseado debe declararse explícitamente. No es posible usar sugerencias de bloqueo (como XLOCK) para garantizar el aislamiento de determinadas filas o tablas de la transacción.

  • La aplicación que accede a la base de datos debe implementar lógica de reintentos para manejar errores causados por conflictos que impidan completar transacciones, fallos de validación y fallos de dependencia de confirmación. Tenga en cuenta que los errores de dependencia de confirmación pueden producirse incluso con transacciones de solo lectura.

  • Las transacciones de larga duración deben evitarse con tablas optimizadas para memoria. Estas transacciones aumentan la probabilidad de conflictos y las posteriores finalizaciones de las transacciones. Una transacción de larga ejecución también aplaza la recolección de basura. Cuanto más tiempo se ejecute una transacción, durante más tiempo OLTP In-Memory mantiene las versiones de fila eliminadas recientemente, lo que puede reducir el rendimiento de búsqueda de nuevas transacciones.

Normalmente, las tablas basadas en disco dependen de bloqueos y obstrucciones para el aislamiento de transacciones. Las tablas optimizadas para memoria dependen de la creación de múltiples versiones y la detección de conflictos para garantizar el aislamiento. Para obtener más información, consulte la sección detección de conflictos, validación y confirmación de comprobaciones de dependencia en transacciones en tablas de Memory-Optimized.

Las tablas de disco permiten el versionado múltiple con los niveles de aislamiento SNAPSHOT y READ_COMMITTED_SNAPSHOT. En el caso de las tablas optimizadas para memoria, todos los niveles de aislamiento se basan en varias versiones, incluidos REPEATABLE READ y SERIALIZABLE.

Tipos de transacciones

Cada consulta de SQL Server se ejecuta en el contexto de una transacción.

Hay tres tipos de transacciones en SQL Server:

  • Transacciones con Autocommit. Si no hay ningún contexto de transacción activo y las transacciones implícitas no se establecen en ON en la sesión, cada consulta tiene su propio contexto de transacción. La transacción comienza cuando la instrucción empieza a ejecutarse y se completa cuando la instrucción termina.

  • Transacciones explícitas. El usuario inicia la transacción a través de un BEGIN TRAN explícito o un BEGIN ATOMIC. La transacción se completa mediante los correspondientes "COMMIT," "ROLLBACK," o "END" (en el caso de un bloque atómico).

  • Transacciones implícitas. Cuando la opción IMPLICIT_TRANSACTIONS se establece en ON, se inicia una transacción implícitamente cada vez que el usuario ejecuta una instrucción y no hay ningún contexto de transacción activo. La transacción se completa mediante un COMMIT y ROLLBACK explícitos.

Aislamiento de nivel base READ COMMITTED

READ COMMITTED es el nivel de aislamiento predeterminado en SQL Server.

El nivel de aislamiento READ COMMITTED garantiza que las transacciones no ven datos no confirmados de los cambios fuera de la transacción actual. Es decir, la transacción solo lee los datos que se han confirmado en la base de datos o que han sido modificados por la transacción actual.

Todos los niveles de aislamiento admitidos para las tablas optimizadas para memoria proporcionan la garantía de lectura confirmada. Por lo tanto, si la transacción no requiere garantías más sólidas, puede usar cualquiera de los niveles de aislamiento admitidos para las tablas optimizadas para memoria. SNAPSHOT utiliza la menor cantidad de recursos del sistema en comparación con otros niveles de aislamiento.

La garantía proporcionada por el nivel de aislamiento SNAPSHOT (el nivel de aislamiento más bajo admitido para las tablas optimizadas para memoria) incluye las garantías ofrecidas por READ COMMITTED. Cada declaración de la transacción lee la misma versión coherente de la base de datos. No solo son confirmadas en la base de datos todas las filas leídas por la transacción, sino que todas las operaciones de lectura también ven el conjunto de cambios realizados por el mismo conjunto de transacciones.

Guía: Si solo se requiere la garantía de aislamiento READ COMMITTED, use el aislamiento SNAPSHOT con procedimientos almacenados compilados de forma nativa y para acceder a tablas optimizadas para memoria mediante Transact-SQL interpretado.

En el caso de las transacciones de confirmación automática, el nivel de aislamiento READ COMMITTED se asigna implícitamente a SNAPSHOT para tablas optimizadas para memoria. Por lo tanto, si la configuración de sesión TRANSACTION ISOLATION LEVEL está establecida en READ COMMITTED, no es necesario especificar el nivel de aislamiento a través de una sugerencia de tabla al acceder a tablas optimizadas para memoria.

En el siguiente ejemplo de transacción de confirmación automática se muestra una combinación entre una tabla optimizada para memoria Clientes y una tabla normal [Historial de pedidos], como parte de un lote ad hoc:

SET TRANSACTION ISOLATION LEVEL READ COMMITTED;  
GO  
SELECT *   
FROM dbo.Customers AS c   
LEFT JOIN dbo.[Order History] AS oh   
    ON c.customer_id = oh.customer_id;  

En el siguiente ejemplo de transacciones explícitas o implícitas se muestra la misma combinación, pero esta vez en una transacción de usuario explícita. Se accede a la tabla optimizada para memoria 'Clientes' bajo aislamiento de instantáneas, como se indica mediante la sugerencia de tabla WITH (SNAPSHOT), y se accede a la tabla normal [Historial de pedidos] en aislamiento de lectura confirmada.

SET TRANSACTION ISOLATION LEVEL READ COMMITTED  
GO  
BEGIN TRAN  
SELECT * FROM dbo.Customers c with (SNAPSHOT)   
LEFT JOIN dbo.[Order History] oh   
    ON c.customer_id=oh.customer_id  
...  
COMMIT  

Diferencias operativas

Además de la garantía de lectura confirmada, también hay dos detalles clave de implementación en los que pueden confiar las aplicaciones que usan tablas basadas en disco. Tenga en cuenta lo siguiente al convertir una tabla basada en disco a la que se accede mediante el aislamiento READ COMMITTED en una tabla optimizada para memoria a la que se accede mediante el aislamiento SNAPSHOT:

  • La implementación del nivel de aislamiento READ COMMITTED para las tablas basadas en disco (suponiendo que READ_COMMITTED_SNAPSHOT es OFF) usa bloqueos para evitar conflictos entre lectores y escritores. Cuando un escritor comienza a actualizar una fila, toma un bloqueo y no libera el bloqueo hasta que se confirma la transacción. Las operaciones de lectura están bloqueadas y esperarán a que la transacción de escritura se confirme.

    Algunas aplicaciones pueden suponer que los lectores siempre esperan a que los escritores realicen su confirmación, especialmente si hay alguna sincronización entre las dos transacciones en la capa de aplicación.

    Directriz: Las aplicaciones no pueden depender del comportamiento de bloqueo. Si una aplicación necesita sincronización entre transacciones simultáneas, esta lógica se puede implementar en el nivel de aplicación o en el nivel de base de datos, a través de sp_getapplock (Transact-SQL).

  • En las transacciones que usan el aislamiento READ COMMITTED, cada instrucción ve la versión más reciente de las filas de la base de datos. Por lo tanto, las instrucciones posteriores reflejan los cambios en el estado de la base de datos.

    Sondear una tabla mediante un bucle WHILE hasta que se haya encontrado una nueva fila es un ejemplo de un patrón de aplicación que usa esta suposición. Con cada iteración del bucle, la consulta verá las actualizaciones más recientes en la base de datos.

    Directriz: Si una aplicación necesita sondear una tabla optimizada para memoria para obtener las filas más recientes escritas en la tabla, mueva el bucle de sondeo fuera del ámbito de la transacción.

    A continuación se muestra un patrón de aplicación de ejemplo que usa esta suposición. Sondear una tabla mediante un bucle WHILE hasta que se encuentre una nueva fila. En cada iteración de bucle, la consulta tendrá acceso a las actualizaciones más recientes de la base de datos.

El script de ejemplo siguiente sondea una tabla t1 hasta que tiene una fila. A continuación, quita una sola fila de la tabla para su posterior procesamiento.

Tenga en cuenta que la lógica de sondeo debe estar fuera del ámbito de la transacción, ya que usa el aislamiento de instantáneas para acceder a la tabla t1. El uso de la lógica de sondeo dentro del ámbito de una transacción crearía una transacción de larga duración, que es una práctica incorrecta.

-- poll table  
WHILE NOT EXISTS (SELECT 1 FROM dbo.t1)  
BEGIN   
  -- if empty, wait and poll again  
  WAITFOR DELAY '00:00:01'  
END  
  
BEGIN TRANSACTION  
  DECLARE @id int  
  SELECT TOP 1 @id=id FROM dbo.t1 WITH (SNAPSHOT)  
  DELETE FROM dbo.t1 WITH (SNAPSHOT) WHERE id=@id  
  
  -- insert processing based on @id  
COMMIT  

Sugerencias de tabla de bloqueo

Las sugerencias de bloqueo (sugerencias de tabla (Transact-SQL)) como HOLDLOCK y XLOCK se pueden usar con tablas basadas en disco para que SQL Server tome más bloqueos de los necesarios para el nivel de aislamiento especificado.

Las tablas optimizadas para memoria no usan bloqueos. Se pueden usar niveles de aislamiento más altos, como REPEATABLE READ y SERIALIZABLE, para declarar las garantías deseadas.

No se admiten sugerencias de bloqueo. En su lugar, declare las garantías requeridas mediante los niveles de aislamiento de transacción. (NOLOCK se admite porque SQL Server no toma bloqueos en tablas optimizadas para memoria. Tenga en cuenta que, a diferencia de las tablas basadas en disco, NOLOCK no implica el comportamiento READ UNCOMMITTED para las tablas optimizadas para memoria).

Véase también

Descripción de transacciones en tablas de Memory-Optimized
Directrices para la lógica de reintento para transacciones en tablas de Memory-Optimized
Niveles de aislamiento de transacciones