Cómo reproducir "No se pudo continuar el escaneo con NOLOCK debido al movimiento de datos"

10

De vez en cuando aparece "No se pudo continuar con el escaneo NOLOCKdebido al movimiento de datos" con algunos trabajos grandes, que tienen WITH (NOLOCK)en las consultas de selección.

Entiendo que esto tiene algo que ver con el intento de seleccionar datos cuando ha habido una división de página que causó que los datos ya no estuvieran donde se suponía que debían estar; supongo que eso es lo que está sucediendo en mi entorno.

¿Cómo reproduciría esto?

Estoy tratando de hacer una solución a corto plazo para detectar el error y volver a intentarlo cuando esto sucede, pero no puedo probarlo si no puedo reproducirlo. ¿Hay una manera razonablemente confiable de causar esto?

Cuando sucede, la ejecución de la consulta nuevamente resulta exitosa, por lo que realmente no tengo ninguna preocupación sobre si los datos reales o la base de datos están permanentemente corruptos. Algunas de las tablas de la consulta (junto con sus índices) se descartan, se recrean y se vuelven a llenar a menudo, por lo que supongo que es algo relacionado con eso.

Eliminar NOLOCKes mi problema a largo plazo con el que lidiar. En NOLOCKprimer lugar, la razón fue que las consultas eran tan malas que estaban bloqueadas con las transacciones diarias, por lo que NOLOCKera una curita para detener los puntos muertos (que funcionó). Así que necesito una curita en una curita hasta que podamos hacer una solución permanente.

Si pudiera reproducirlo con Hello World, probablemente planearía poner la curita en el trabajo en menos de una hora. No puedo hacer una eliminación de búsqueda y reemplazo NOLOCK, porque comenzaría a obtener los puntos muertos de la aplicación nuevamente, lo que es peor para mí que un trabajo de falla ocasional.

El uso del aislamiento de instantáneas comprometido con la lectura es una buena posibilidad: tendré que trabajar con nuestro equipo de base de datos para obtener más detalles al respecto. Parte de nuestro problema es que no tenemos un experto en SQL Server para hacer frente a ese tipo de cosas, y no entiendo los niveles de aislamiento lo suficientemente bien como para hacer ese cambio en este momento.

wookie23
fuente
1
¿Has considerado simplemente retirarte NOLOCKde estos trabajos? 601 debería ser la menor de sus preocupaciones si se supone que los resultados de estas consultas son precisos . Paul White muestra un ejemplo particularmente terrible de lectura de datos que no debería ser posible aquí .
Aaron Bertrand
3
También podemos establecer DEADLOCK_PRIORITYque LOWen los puestos de trabajo, por lo que si hay puntos muertos, los puestos de trabajo se producirá un error, y no las aplicaciones. Después de eso, podría investigar los puntos muertos y descubrir por qué están sucediendo, y solucionar ese problema. Podría ser una solución muy simple, como intercambiar el orden de dos declaraciones. Cualquiera que sea el problema, noNOLOCK es la solución , así que deja de intentar forzarlo a ser solo porque eso es más fácil.
Aaron Bertrand
@AaronBertrand Gracias, no sabía acerca de DEADLOCK_PRIORITY. Lo investigaré. Intentamos rastrear los puntos muertos, pero sucedieron en varios momentos aparentemente aleatorios, y solo una o dos veces al día, y nunca son reproducibles a pedido: nuestros trabajos programados ejecutan decenas de miles de consultas cada hora, y nuestra aplicación ejecuta cientos de consultas cada vez que solo carga una página o guarda algo, y no hemos rastreado qué consulta en ambos lados está involucrada en el punto muerto. No tenía intención de dejar NOLOCK allí para siempre, por eso estamos investigando mejores soluciones a largo plazo.
wookie23
1
Usted mencionó que estaba teniendo dificultades para rastrear los puntos muertos. Dado que usted está en 2008 R2, puede mirar aquí: sqlservercentral.com/articles/deadlock/65658 Jonathan Kehayias repasa la información del punto muerto del búfer de anillo.
Kenneth Fisher
Las respuestas y los comentarios abordan bien el problema subyacente, pero ¿todavía está interesado en encontrar una manera de reproducir esto como un ejercicio intelectual?
James L

Respuestas:

8

Dado que un posible 'curita' para los problemas de NOLOCK es dejar de usar NOLOCK y comenzar a usar el aislamiento READ_COMMITTED_SNAPSHOT, quiero señalarle la publicación del blog en http://www.brentozar.com de Kendra Little: Implementación de instantánea o lectura comprometida Aislamiento de instantáneas en SQL Server: una guía .

Kendra proporciona una buena cantidad de detalles sobre los beneficios y riesgos al usar el nivel de aislamiento READ_COMMITTED_SNAPSHOT.

  1. Este nivel de aislamiento se convierte en el nivel de aislamiento predeterminado para el código de la base de datos.
  2. Debe tener un solo usuario en la base de datos para realizar el cambio al nivel de aislamiento READ_COMMITTED_SNAPSHOT.
  3. Incluso si utiliza el aislamiento READ_COMMITTED_SNAPSHOT , deberá eliminar las sugerencias NOLOCK, ya que anulan el valor predeterminado.
  4. Algunos de sus códigos pueden tener problemas que necesitan curarse.

Hace algunos años implementamos el aislamiento READ_COMMITTED_SNAPSHOT en una base de datos que sufría graves bloqueos . Pero una vez que cambiamos el nivel de aislamiento, comenzamos a tener puntos muertos en un par de áreas críticas.

¿Por qué pasó esto? Debido a que el nivel de aislamiento anterior causó un fuerte bloqueo, el código "nunca" podría llegar al punto de bloqueo. Sin embargo, con el aislamiento READ_COMMITTED_SNAPSHOT, las consultas podrían seguir avanzando. Sin embargo, un porcentaje de las transacciones que ya no están en espera comenzó a llegar a un punto muerto.

Afortunadamente, nuestro caso se resolvió rápidamente determinando los puntos muertos y ajustando los índices en un par de tablas para tener un orden de columnas más racional. Esto redujo en gran medida nuestros problemas de bloqueo.

RLF
fuente