2009-05-11 16 views
7

Tengo una aplicación VB6 que accede a una sola tabla en un servidor MSSQL2000 a través de ADO. Estoy usando acceso de solo lectura (adOpenStatic, adLockReadOnly). Hay otras aplicaciones en la red que realizan cambios en la tabla.¿Es posible crear un interbloqueo con acceso de solo lectura?

Por alguna razón, recibo errores sobre mi aplicación como víctima de interbloqueo.

Estoy muy confundido: ¿Por qué puede haber un punto muerto cuando estoy simplemente leyendo desde una sola tabla? Esperaría tiempos de espera, debido a la escritura de las otras aplicaciones, pero no a un punto muerto ...

¿Alguien puede arrojar algo de luz sobre esto?

ACTUALIZACIÓN: 2009-06-15 Todavía estoy interesado en una solución a este problema. Así que estoy proporcionando algo más de información:

  • no hace ninguna diferencia si decido adOpenForwardOnly o adOpenStatic
  • No hace ninguna diferencia si la posición del cursor es cliente o servidor.
+2

Espero que hayas aprendido que un READ definitivamente puede estancarse, muchas respuestas han señalado cómo sucede esto. Ahora necesita hacer su tarea y dar el resto de la información, es decir. quién está bloqueando * con * y el gráfico de interbloqueo. –

+0

Desafortunadamente, solo puedo reproducir el problema en el sistema de producción, así que tengo que tomarlo con calma y no apresurar nada. Además, solo puedo acceder al servidor a través de una extraña combinación de VPN/VNC/Escritorio remoto/Herramienta de transferencia de archivos personalizada (no preguntar), por lo que incluso un solo control o copiar un nuevo archivo ejecutable requiere años. –

Respuesta

12

Es posible que una sola instrucción SELECT a punto muerto contra un solo UPDATE o DELETE debido a la presencia de un índice no agrupado, considere la situación siguientes aparatos:

El lector (su aplicación) primero obtiene una bloqueo compartido en el índice no agrupado para realizar una búsqueda, y luego intenta obtener un bloqueo compartido en la página que contiene los datos para devolver los datos.

El escritor (otra aplicación) primero obtiene un bloqueo exclusivo en la página de la base de datos que contiene los datos, y luego intenta obtener un bloqueo exclusivo en el índice para actualizar el índice.

Puede encontrar más información sobre este (y otros) tipo de punto muerto en el artículo Q169960 de Microsoft Knowledge (http://support.microsoft.com/kb/q169960/)

También es posible que desee echar un vistazo en Google sobre cómo obtener información de traza de interbloqueo (traza flag 1222) - esto informará exactamente sobre qué declaraciones SQL están en conflicto sobre qué objetos cada vez que se produce un punto muerto. Este es un artículo de mirar bastante decente - http://blogs.msdn.com/bartd/archive/2006/09/09/747119.aspx

+0

En cuanto a Entiendo que las marcas de traza son globales, es decir, afectan a cada conexión. Como el problema solo ocurre en el servidor de producción, tengo que esperar un período de tiempo en el que pueda hacerlo sin correr ningún riesgo. –

+0

Sí, son globales, sin embargo, hay muchas poco impacto en el rendimiento del registro extra. IMO es una buena idea dejar este indicador habilitado en los servidores de producción para que esté seguro de capturar información de interbloqueo cada vez que ocurra (los interbloqueos son difíciles de reproducir), pero no soy un DBA. .. – Justin

-1

¿No sería algo como esto?

otra aplicación: grabar en la tabla (adquisición de bloqueo de escritura en la tabla)

su aplicación: Leer de la tabla (adquisición de bloqueo de lectura en la mesa, no puede debido a escribir bloqueo).

+0

En mi experiencia eso solo bloquearía mi aplicación y eventualmente produciría un tiempo de espera –

+1

No lo utilicé yo mismo, pero aparentemente el indicador de rastreo 1204 en SQL Server lo ayudará a determinar dónde está pasando el punto muerto. Ver http://msdn.microsoft.com/en-us/library/ms178104.aspx –

-1

Depende del comportamiento de ambas aplicaciones. su aplicación seguramente puede esperar en el otro para liberar recursos.

+0

Sí, ese sería el comportamiento normal que observé en muchas otras aplicaciones: bloqueo y tal vez un tiempo de espera. –

0

Las lecturas aún pueden provocar bloqueos, para que el DB se asegure de que no se realice una escritura en medio de una lectura no atómica. En otras palabras, el bloqueo de lectura garantiza que obtendrá una instantánea consistente y precisa de los datos que elija.

-1

Un punto muerto se refiere a una condición cuando dos o más procesos están esperando el uno al otro para liberar un recurso, o más de dos procesos están esperando recursos en una cadena circular. Claro que puede crear un interbloqueo con acceso de solo lectura porque la lectura NO esperará.

Hay una buena explicación acerca de las condiciones de estancamiento en el wikipedia

+1

"Claro que puedes crear un interbloqueo con acceso de solo lectura porque la lectura NO esperará" - eso no tiene sentido para mí. –

0

¿Usted consigue el mismo comportamiento con adOpenForwardOnly?

Es posible que desee comprobar que las estadísticas de su servidor SQL estén actualizadas. O puede obtener su DBA para reconstruir todos los índices. Muchos problemas de bloqueo se deben a estadísticas/índices desactualizados.

+0

No puedo reproducir el problema a voluntad, tengo que esperar y ver ... –

+0

No hace la diferencia :( –

+0

... y ha comprobado que todos los índices/estadísticas están actualizados? –

3

Creo que hay una serie de posibilidades en las respuestas ya proporcionadas aquí. Como solo toma bloqueos compartidos, el interbloqueo no puede deberse a una escalada de bloqueo, y simplemente debe adquirir bloqueos que son incompatibles con los adquiridos en otro proceso, y adquirir esos bloqueos en un orden diferente ...

Su los bloqueos compartidos son incompatibles con otro proceso que toma bloqueos exclusivos. El escenario podría ejecutar algo como esto ...

  1. lo lleve bloqueo en el recurso compartido un
  2. Otro proceso de toma bloqueo exclusivo en el recurso B
  3. otro proceso intenta tomar bloqueo exclusivo en el recurso A, y los bloques esperando que libere su bloqueo compartido en A.
  4. Intenta tomar el bloqueo compartido en el recurso B, y bloquearía la espera de que el otro proceso libere su bloqueo exclusivo en B, excepto que ahora se encuentra en una situación de punto muerto , que es identificado por el servidor y elige un proceso para matar.

N.B. los puntos muertos pueden tener más jugadores que solo 2. A veces hay toda una cadena de actividad entrelazada que resulta en un punto muerto, pero el principio es el mismo.

A menudo, si varias aplicaciones acceden a la misma base de datos, hay un administrador de base de datos que gestiona todos los accesos a través de procedimientos almacenados, por lo que puede garantizar que los recursos estén siempre bloqueados en el mismo orden. Si no estás en esa situación, y las otras aplicaciones usan sentencias SQL ad-hoc, deberías inspeccionar su código para descubrir si pueden entrar en conflicto con tu aplicación de la manera que he descrito. Eso no suena divertido.

Una solución pragmática podría ser detectar el error cuando se cancela la transacción como víctima de interbloqueo, y simplemente volver a intentar la transacción varias veces. Dependiendo de la cantidad de actividad que generen las otras aplicaciones, puede obtener resultados aceptables de esta manera.

Cuestiones relacionadas