2012-08-06 21 views
7

Tengo una consulta de selección compleja y una tabla enorme.Servidor SQL: ¿[SELECCIONAR] bloquear [ACTUALIZAR]?

estoy corriendo esta declaración select, por su parte una declaración Update llega y trata de actualización de la tabla.

mi humilde opinión - de actualización requiere un bloqueo exclusivo - por lo que la instrucción de actualización tendrá que esperar hasta que se termina el comando select.

  1. Am I right?

  2. ¿qué puedo hacer con el fin de: ejecutar el complejo select, y también dejar correr el comando update (actualmente no se preocupan por los datos sucios)

+1

¿De qué nivel de aislamiento de transacción está hablando? – Oded

+0

@Oded El valor predeterminado: creo que se ha leído. –

+3

* "actualmente no me importan los datos sucios" *: tenga cuidado [lo que desea] (http://blogs.msdn.com/b/sqlcat/archive/2007/02/01/previously-committed- rows-might-be-missed-if-nolock-hint-is-used.aspx). –

Respuesta

13

Sí - a un grado

el tiempo que un SELECT se aferra a un bloqueo compartido está en función del nivel de aislamiento de la transacción:

  • READ UNCOMMITTED - sin bloqueo compartido se adquiere en absoluto - UPDATE no está bloqueado
  • READ COMMITTED - Compartido el bloqueo se adquiere solo mientras dure la lectura de los datos: UPDATE puede estar bloqueado durante un período de tiempo muy corto
  • REPEATABLE READ y SERIALIZABLE - el bloqueo compartido se adquiere y mantiene en unti l al final de la transacción - UPDATE se bloquea hasta que la transacción SELECT termina

Técnicamente, la declaración UPDATE primera consigue un bloqueo UPDATE - que es compatible con un bloqueo compartido (tal como se utiliza por el SELECT) - para la duración del tiempo mientras lee los valores actuales de las filas a actualizar.

Una vez hecho esto, el bloqueo Update se escala a un bloqueo exclusivo para que los nuevos datos se escriban en la tabla.

+0

'la instrucción UPDATE primero obtiene un bloqueo UPDATE, que es compatible con un bloqueo compartido' No entiendo marc. la actualización está esperando para seleccionar para terminar? –

+1

@RoyiNamir: la actualización puede adquirir el bloqueo 'Update' (para leer los datos" antiguos ") mientras que otro proceso sigue leyendo esa misma fila y tiene un bloqueo' shared' en esa fila. Sin embargo, la actualización no podrá ir a un candado exclusivo (para volver a escribir los datos "nuevos"), siempre y cuando el candado 'shared' esté todavía en su lugar, por lo que tendrá que esperar allí ... . –

5

Cuando ejecuta las dos declaraciones al mismo tiempo (un SELECT y una ACTUALIZACIÓN) el comportamiento real será básicamente aleatorio. Esto es porque ninguna de las operaciones es instantánea. Para simplificar, considere su tabla una lista y SELECCIONAR está atravesando esta lista, mirando una fila a la vez. ACTUALIZAR también está tratando de actualizar una o más filas. Cuando la actualización está tratando de actualizar una fila detrás de SELECT, no ocurre nada (sin bloqueo) porque el SELECT ya ha progresado más allá del punto de ACTUALIZACIÓN. Si la actualización está tratando de actualizar la fila en la que SELECT está buscando en este momento, entonces la actualización tendrá que esperar que SELECT continúe, lo que ocurrirá muy, muy muy rápido y la actualización se desbloqueará y tendrá éxito, mientras que SELECT está avanzando. Pero si la ACTUALIZACIÓN está actualizando una fila adelante del SELECTO entonces la actualización tendrá éxito y, más tarde, SELECCIONARÁ finalmente llegará exactamente a esta fila y se detendrá, bloqueado.Ahora SELECT tiene que esperar hasta que la transacción que realizó UPDATE confirme.

Esta es la historia simplificada. La vida real es mucho más complicada. El SELECCIONAR puede tener puntos de lectura múltiples (planes paralelos). Tanto el SELECCIONAR como la ACTUALIZACIÓN están sujetas a elegir una ruta de acceso, es decir, usar uno o más índices secundarios para ubicar las filas. Las consultas complejas pueden contener operadores que causan búsquedas múltiples en una tabla (por ejemplo, uniones). Tanto SELECT como UPDATE pueden hacer búsquedas en los marcadores para obtener datos BLOB, lo que cambia significativamente el comportamiento de bloqueo. La estimación de cardinalidad puede hacer que SELECT se ejecute en un modo de bloqueo de granularidad alta (por ejemplo, bloqueo compartido de nivel de tabla). La ACTUALIZACIÓN puede desencadenar escalada de bloqueo y la escalada puede fallar o tener éxito. Choosing different access paths can lead to deadlock. False lock contention can occur due to hash collisions. Hay casi una miríada de variables que tienen voz en esto. Y ni siquiera mencioné niveles de aislamiento más altos (lectura repetible, serializable).

Quizás debería usar el aislamiento SNAPSHOT y dejar de preocuparse por este problema?

+0

Si sugiere ir con 'SNAPSHOT' - ¡simplemente asegúrese de que' TempDB' esté configurado correctamente! (ubicación y número de archivos de datos, opciones de tamaño, etc.) –

+1

Sí, repetible y serializable, causa que el bloqueo compartido se retenga para el alcance de la transacción. Serializable también agrega bloqueos de rango. Todos estos agregan complejidad. –

+1

@marc_s: el enlace al tema de MSDN cubre [Uso de recursos de control de filas] (http://msdn.microsoft.com/en-us/library/ms175492 (v = sql.105)). Prefiero no asustar a los usuarios, ya que considero que los beneficios de SNAPSHOT superan con creces su costo. –

Cuestiones relacionadas