SQL Server en la práctica

NOLOCK: una respuesta rápida puede ser incorrecta

Reproduzca una lectura sucia con dos sesiones, entienda los bloqueos restantes y sustituya NOLOCK conservando la exactitud de sus informes.

Un informe que termina en dos segundos puede ser menos útil que otro que espera cinco si su total nunca existió en datos confirmados. NOLOCK cambia lo que una lectura puede observar. En facturación, inventario y decisiones operativas, eso modifica el significado del resultado. No es simplemente una forma más barata de ejecutar la misma consulta.

Reproducir el error de lectura

Utilice una base desechable y dos ventanas conectadas a esa misma base. Ejecute la preparación una vez. En la ventana A, abra la transacción y déjela activa. En B, ejecute la consulta NOLOCK antes de volver a A y deshacer la operación.

CREATE TABLE dbo.NolockDemo (Id int PRIMARY KEY, Balance int NOT NULL);
INSERT dbo.NolockDemo VALUES (1, 100);
BEGIN TRAN;
UPDATE dbo.NolockDemo SET Balance = 900 WHERE Id = 1;
-- Run the reader in window B, then execute:
-- ROLLBACK;
SELECT Balance FROM dbo.NolockDemo WITH (NOLOCK) WHERE Id = 1;

B puede mostrar 900 aunque ese saldo nunca se confirme. Después del rollback, el valor confirmado sigue siendo 100. Una lectura normal con READ COMMITTED basado en bloqueos puede esperar durante el experimento. Si READ_COMMITTED_SNAPSHOT está activado, puede leer la versión previamente confirmada. Compruebe la opción antes de interpretar el resultado. Una respuesta inmediata no demuestra que la aplicación necesite NOLOCK.

La anomalía es más difícil de reconocer cuando el informe combina varias tablas. Un saldo puede corresponder a una fase de la transacción y los movimientos relacionados a otra. Durante cambios físicos concurrentes también pueden omitirse filas o leerse varias veces. Que la siguiente ejecución produzca el total esperado no valida el resultado anterior. La intermitencia hace especialmente complicada la investigación de estos incidentes.

Investigar la espera original

NOLOCK sigue necesitando bloqueos de estabilidad del esquema durante compilación y ejecución. Un cambio de esquema puede bloquear la consulta, y una consulta prolongada puede retrasar ese cambio. Tampoco elimina trabajo de CPU, desbordamientos de ordenación, transferencias de red ni lecturas de almacenamiento. Analice el tipo real de espera antes de modificar el aislamiento.

Capture la consulta lectora, el bloqueador principal, sus instrucciones y la antigüedad de la transacción. Si la aplicación mantiene una transacción abierta mientras consulta un servicio externo, corrija su duración. Si el informe recorre millones de filas irrelevantes, revise filtros e índices. Si un panel solicita toda la historia para mostrar tres cifras, considere una agregación actualizada por separado. Son problemas diferentes y requieren pruebas diferentes.

Establezca la consistencia requerida. ¿Basta una vista confirmada para cada instrucción? ¿Deben varias instrucciones compartir el mismo estado? ¿Se acepta un corte explícitamente antiguo? READ_COMMITTED_SNAPSHOT ofrece consistencia por instrucción, mientras SNAPSHOT puede ofrecerla por transacción. Una réplica de lectura puede estar retrasada respecto al escritor y no vuelve coherente automáticamente cualquier secuencia de consultas.

Sustituir el hint con evidencia

Comience por un informe cuyo resultado pueda comprobarse de forma independiente. Quite NOLOCK en un entorno representativo, mida duración y lecturas lógicas, y ejecute escritores concurrentes. Si considera versionado de filas, evalúe capacidad del almacén de versiones, lectores prolongados y transacciones existentes. Una opción de base de datos afecta a mucho más que el informe que originó la investigación.

La prueba de aceptación debe repetir el ejemplo del saldo y confirmar que nunca se publique el importe sin confirmar. Añada una transacción sobre varias tablas siguiendo el orden real de la aplicación. Verifique una regla de negocio, como la igualdad entre cabecera de factura y suma de sus líneas. Recibir HTTP 200 desde el informe no demuestra esa igualdad.

Registre por separado latencia y exactitud. La sustitución funciona cuando entrega una vista confirmada aceptable con actividad concurrente y cumple el plazo de respuesta. Cierre explícitamente la transacción de práctica mediante ROLLBACK y elimine después la tabla. NOLOCK debe representar una relajación conscientemente aceptada para un caso concreto, nunca una convención copiada a todas las consultas.

Referencias técnicas: Microsoft Learn: Table hints · Microsoft Learn: Transaction isolation.

Pregunta sobre este artículo

¿Tiene alguna pregunta sobre este tema?

Cuéntenos qué está evaluando o dónde tiene dificultades. Le responderemos con una recomendación práctica.

Inquiries are not enabled in this preview.

Hacer una pregunta sobre este artículo