2009-06-19 29 views
14

Estamos usando una base de datos SQL Server 2005 (sin versiones de filas) con una enorme instrucción de selección, y estamos viendo que bloquea otras declaraciones (se usa sp_who2). No me di cuenta de que las instrucciones SELECT podrían causar bloqueo, ¿hay algo que pueda hacer para mitigar esto?SQL Server Sentencias SELECT causantes de bloqueo

+0

¿Utiliza más altos niveles de aislamiento, por casualidad, al igual que la lectura repetible o serializable? Algunos componentes de ADO y CLR entran sigializable sin su consentimiento explícito ... ¿Cuál es el recurso de bloqueo en (clave, rango, tabla)? –

+0

No estoy especificando el nivel de aislamiento. ¿Hay alguna manera de averiguar qué nivel de aislamiento está en uso? –

+1

Sí, consulte sys.dm_exec_sessions. columna transaction_isolation_level –

Respuesta

27

SELECT puede bloquear actualizaciones. Un modelo de datos y una consulta diseñados correctamente solo causarán un bloqueo mínimo y no serán un problema. La sugerencia "usual" de NOLOCK es casi siempre la respuesta incorrecta. La respuesta correcta es ajustar su consulta para que no explore tablas enormes.

Si la consulta es untunable entonces primero debe considerar SNAPSHOT ISOLATION level, en segundo lugar se debe considerar el uso DATABASE SNAPSHOTS y última opción debe ser lecturas sucias (y es mejor cambiar el isolation level en lugar de utilizar la sugerencia NOLOCK). Tenga en cuenta que las lecturas sucias, como el nombre indica claramente, arrojarán datos incoherentes (por ejemplo, su hoja total puede estar desequilibrada).

+1

que en otra pregunta: ¿http://stackoverflow.com/questions/1018651/nolock-vs-transaction-isolation-level/1018676#1018676 –

+2

No me consiga equivocado, una excelente respuesta, pero trato de no hablar en términos absolutos sin saber nada sobre su aplicación y diseño. Por ejemplo, ¿qué ocurre si su aplicación es una aplicación Enterprise que tiene una función de "Consulta"? ¿Adivina quién está escribiendo tu consulta? ¿A su base de datos? ¡El cliente! ¡¡No hay suficientes índices !! Niveles de aislamiento de instantáneas ¿Cuántas personas golpean simultáneamente sus bases de datos? Porque hablemos de recursos con esta opción !! Entonces, sí, ¡las masas sucias que no son gurús de DB deben usar una lectura sucia! – JustLooking

+0

@JustLooking tiene buenos puntos, pero creo que la respuesta de Remus es una buena guía - esp. su primer argumento que requiere sugerencias de nolock es que hay algo mal con el diseño general o la consulta. Además, ¿qué pasa con un db que usa transacciones? ¿No debería eso indicar que nolock debería evitarse? Parece que crearía muchos errores oscuros y difíciles de probar porque son intermitentes. – MorganTiley

14

De documentation:

Shared (S) cerraduras permiten transacciones concurrentes para leer (SELECT) un recurso bajo el control de concurrencia pesimista. Para obtener más información, consulte Types of Concurrency Control. Ninguna otra transacción puede modificar los datos mientras existan bloqueos shared (S) en el recurso. Shared (S) bloqueos en un recurso se liberan tan pronto como se complete la operación de lectura, a menos que el nivel de aislamiento de transacción se establezca como lectura repetible o superior, o se use una sugerencia de bloqueo para retener los bloqueos shared (S) durante la transacción.

A shared lock es compatible con otro bloqueo compartido o un bloqueo de actualización, pero no con un bloqueo exclusivo.

Eso significa que sus consultas SELECT bloquearán las consultas UPDATE y INSERT y viceversa.

Una consulta SELECT colocará un bloqueo compartido temporal cuando lea un bloque de valores de la tabla, y lo eliminará cuando lo haya leído.

Por el tiempo que existe el bloqueo, no podrá hacer nada con los datos en el área bloqueada.

Dos SELECT consultas nunca se bloquean entre sí (a menos que sean SELECT FOR UPDATE)

Puede habilitar nivel SNAPSHOT aislamiento en su base de datos y el uso de ella, pero tenga en cuenta que no va a evitar que UPDATE consultas de ser bloqueado por SELECT consultas (que parece ser tu caso).

Sin embargo, evitará que las consultas SELECT se bloqueen por UPDATE.

También tenga en cuenta que SQL Server, a diferencia de Oracle, utiliza el administrador de bloqueos y lo mantiene bloqueado en una lista enlazada en la memoria.

Eso significa que bajo una carga pesada, el solo hecho de colocar y quitar un bloqueo puede ser lento, ya que la lista vinculada debe estar bloqueada por el hilo de la transacción.

+1

No asuma los detalles de implementación sobre el administrador de bloqueo de SQL Servere. Basta con decir que * no * es una lista vinculada. –

+0

¡Explicación muy clara de los bloqueos! ¡Gracias! –

+0

¿Hay alguna forma de evitar el bloqueo compartido en MySQL? Intenté usar cada nivel de aislamiento disponible, pero ninguno de ellos impide que las consultas de actualización se bloqueen mediante la selección (que es mi caso). –

0

Se podría establecer el transaction level a la lectura no confirmada

+0

¿No es lo mismo que usar (NOLOCK)? Realmente no quiero ir en esa dirección ... –

+0

Es lo mismo que NOLOCK, y está bien para consultas de solo lectura. – Andomar

+2

No, no está bien para consultas sólo de leer, ya que puede NOLOCK * * Sólo se aplicará a consultas de sólo lectura, por lo que cualquier problema que tiene (y tiene un montón) se aplica a 'sólo lectura' también. Un informe de hoja no balanceada sigue siendo de "solo lectura", pero apenas correcto. Citado –

2

Para realizar lecturas sucias, puede:

using (new TransactionScope(TransactionScopeOption.Required, 
new TransactionOptions { 
IsolationLevel = System.Transactions.IsolationLevel.ReadUncommitted })) 
{ 
//Your code here 
} 

o

SelectCommand = "SELECT * FROM Table1 WITH (NOLOCK) INNER JOIN Table2 WITH (NOLOCK) ..." 

recordar que usted tiene que escribir con (NOLOCK) después de cada tabla que desea sucia leer

0

Usted también puede obtener los puntos muertos:

"puntos muertos que implican solamente una mesa" http://sqlblog.com/blogs/alexander_kuznetsov/archive/2009/01/01/reproducing-deadlocks-involving-only-one-table.aspx

y resultados incorrectos o:

"Selecciona menores de lectura confirmada y lectura REPETIBLE puede devolver resultados incorrectos"

http://www2.sqlblog.com/blogs/alexander_kuznetsov/archive/2009/04/10/selects-under-read-committed-and-repeatable-read-may-return-incorrect-results.aspx

Cuestiones relacionadas