2010-02-11 14 views
25

Tengo dos consultas de larga ejecución que están tanto en las transacciones como en el acceso a la misma tabla, pero filas completamente separadas en esas tablas. Estas consultas también realizan algunas actualizaciones e inserciones basadas en esas consultas.¿Cuándo actualizo/inserto una sola fila si bloquea toda la tabla?

Parece que cuando se ejecutan al mismo tiempo que encuentran un bloqueo de algún tipo y está impidiendo que la tarea finalice y se bloquea cuando se va a actualizar una de las filas. Estoy usando un bloqueo de fila exclusivo en las filas que se leen y el bloqueo que aparece en el proceso es un bloqueo lck_m_ix.

dos preguntas:

  1. Cuando puedo actualizar/insertar una sola fila Qué bloquear toda la tabla?
  2. ¿Qué se puede hacer para evitar este tipo de problema?

Respuesta

20

Normalmente no, pero depende (respuesta más frecuentemente utilizado para SQL Server!)

SQL Server tendrá que bloquear los datos implicados en una transacción de alguna manera. Tiene que bloquear los datos en la tabla y los datos con los índices afectados, mientras realiza una modificación. Para mejorar la simultaneidad, hay varias "granularidades" de bloqueo que el servidor podría decidir usar, para permitir la ejecución de múltiples procesos: bloqueos de fila, bloqueos de página y bloqueos de tabla son comunes (hay más). Qué escala de bloqueo está en juego depende de cómo el servidor decide ejecutar una actualización determinada. Para complicar las cosas, también hay clasificaciones de bloqueos como exclusivo compartido, exclusivo e intento exclusivo, que controlan si el objeto bloqueado se puede leer y/o modificar.

Según mi experiencia, SQL Server utiliza principalmente bloqueos de página para cambios en pequeñas porciones de tablas, y más allá de un umbral escalará automáticamente a un bloqueo de tabla, si una porción más grande de una tabla parece afectada por una actualización o eliminación. La idea es que bloquear una tabla (un bloqueo) sea más rápido que obtener y administrar miles de bloqueos de fila o página individuales para una gran actualización.

Para ver lo que está sucediendo en su caso específico, debería consultar la lógica de la consulta y, mientras se está ejecutando, examine las condiciones de bloqueo/bloqueo en sys.dm_tran_locks, sys.dm_os_waiting_tasks u otros DMV. Desearía descubrir qué es exactamente lo que está bloqueado por qué paso en cada uno de sus procesos, para descubrir por qué uno está bloqueando al otro.

1

Diferentes bases de datos tienen diferentes mecanismos de bloqueo, pero algunas como SQL Server y Oracle tienen diferentes tipos de bloqueo.

El valor predeterminado en SQL Server parece ser un bloqueo de página pesimista, por lo que si tiene un número pequeño de registros, entonces todos pueden bloquearse.

La mayoría de las bases de datos no deben bloquearse cuando se ejecuta un script, por lo que me pregunto si puede ejecutar varias consultas al mismo tiempo sin realizar transacciones.

+0

Siempre utilizo consejos de bloqueo, así que estoy usando explícitamente a with (rowlock) para no terminar con un pagelock – Middletone

18

La versión corta:

  1. Sin
  2. arreglar su código.

La versión larga:

LCK_M_IX es un bloqueo con intención, es decir, la operación va a colocar un bloqueo X en un elemento subordinado. P.ej.Al actualizar una fila en una tabla, la tabla de operaciones toma un bloqueo IX en la tabla antes de bloquear X la fila que se está actualizando/insertando/eliminando. Los bloqueos de intención son una estrategia común para manejar jerarquías, como tabla/página/fila, porque el administrador de bloqueos no puede entender la estructura física de los recursos solicitados para ser bloqueados (es decir, no puede saber que un X-lock en la página P1 es incompatible con S-lock en la fila R1 porque R1 está en P1). Para más detalles, vea Lock Modes.

El hecho de que esté viendo contención en bloqueos intencionados significa que está tratando de obtener bloqueos de objeto de alto nivel, como bloqueos de tabla. Necesitará analizar su código fuente para la solicitud que está siendo bloqueada (la que solicita el bloqueo incompatible con LCK_M_IX) y eliminar la causa de la solicitud de bloqueo de nivel de objeto. Lo que eso significa dependerá de tu código fuente, no sé lo que estás haciendo allí. Supongo que utilizas una sugerencia de bloqueo errónea.

Un enfoque más general es confiar en SNAPSHOT ISOLATION. Pero esto, muy probablemente, no resolverá el problema que está viendo, ya que el aislamiento de instantáneas solo puede beneficiar los problemas de contención a nivel de fila, no las aplicaciones que solicitan bloqueos de tabla.

9

Un objetivo frecuente del uso de transacciones: manténgalas lo más cortas y dulces posibles. Me da sentido a su fraseología en la pregunta de que está abriendo una transacción y luego haciendo todo tipo de cosas, algunas de las cuales toman mucho tiempo. Luego, espera que varios usuarios puedan ejecutar este mismo código al mismo tiempo. Desafortunadamente, si realiza una inserción al comienzo de ese conjunto de códigos, luego realiza otras 40 acciones antes de confirmar o retroceder, es posible que esa inserción bloquee a todos los demás para que no ejecuten el mismo tipo de inserción, lo que esencialmente cambiará su operación de libre para todos a la serie.

Averigüe qué hace cada consulta, y si obtiene escaladas de bloqueo que no espera. El hecho de que digas WITH (ROWLOCK) en una consulta no significa que SQL Server pueda cumplir ... si tocas varios índices, vistas indexadas, columnas calculadas persistentes, etc., entonces hay todo tipo de razones por las cuales tu rowlock no puede contener agua También puede tener cosas posteriores en la transacción que tarden más de lo que cree, y tal vez no se da cuenta de que los bloqueos de todos los objetos involucrados en la transacción (no solo la declaración que se está ejecutando actualmente) se pueden retener para la duración de la transacción.

+1

Hola Aaron, ¿Puedes elaborar cuando las "columnas calculadas persistentes" causan más bloqueo, cuando no están indexadas, por supuesto? . Gracias. –

+1

Lo siento Alex, déjame reformular. Lo que quise decir es cuando tocas columnas computadas persistentes que también se indexan. –

Cuestiones relacionadas