sql >> Base de Datos >  >> RDS >> Sqlserver

Pregunta de interbloqueo de SQL

Los SELECT no pueden interbloquearse con otros SELECT, porque solo adquieren bloqueos compartidos. Usted dice que deberíamos considerar que estos SELECT ahora 'requieren bloqueos de lectura exclusivos', pero esto no es posible para nosotros porque 1) no existe tal cosa como un exlusive read lock y 2) las lecturas no adquieren bloqueos exclusivos.

Pero plantea una pregunta más general, si las declaraciones simples pueden bloquearse. La respuesta es un definitivo y rotundo. . Los bloqueos se adquieren en la ejecución, no se analizan por adelantado y se clasifican y luego se adquieren en algún orden. Sería imposible que el motor supiera por adelantado los bloqueos necesarios porque dependen de los datos reales en el disco, y para leer los datos que el motor necesita... bloquear los datos.

Los interbloqueos entre sentencias simples (SELECt vs. UPDATE o SELECT vs. DELETE) debido a diferentes órdenes de acceso al índice son bastante comunes y muy fáciles de investigar, diagnosticar y solucionar. Pero tenga en cuenta que hay siempre una operación de escritura involucrada, ya que las lecturas no pueden bloquearse entre sí. Para esta discusión, agregar una sugerencia UPDLOCK o XLOCK a SELECT debe considerarse una escritura. Ni siquiera necesita un JOIN, un índice secundario bien puede presentar el problema del orden de acceso que lleva a un interbloqueo, consulte Lectura/Escritura Interbloqueo .

Y finalmente, escribiendo SELECT FROM A JOIN B o escribiendo SELECT FROM B JOIN A es completamente irrelevante. El optimizador de consultas es libre de reorganizar el orden de acceso como mejor le parezca, el texto real de la consulta no impone el orden de ejecución de ninguna manera.

Actualizado

Me temo que no hay una receta para cortar galletas. La solución dependerá de cada caso. En última instancia, en las aplicaciones de bases de datos, los interbloqueos son una realidad. Entiendo que esto puede sonar absurdo, como 'aterrizamos en la Luna pero no podemos escribir una aplicación de base de datos correcta', pero hay fuertes factores en juego que garantizan que las aplicaciones eventualmente encontrarán bloqueos. Los puntos muertos afortunados son los más fácil de manejar los errores, simplemente lea nuevamente el estado, aplique la lógica, vuelva a escribir el nuevo estado. Ahora que se ha dicho eso, hay algunas buenas prácticas que pueden reducir drásticamente la frecuencia de los interbloqueos, hasta el punto en que casi desaparecen:

  • Intente tener un patrón de acceso consistente para Escrituras . Tener reglas claramente definidas que establezcan cosas como 'una transacción siempre se incluirá en las tablas en este orden:Customers -> OrderHeaders -> OrderLines .' Tenga en cuenta que la orden debe obedecerse dentro de una transacción . Básicamente, clasificar todos tablas en su esquema y especifique que todas las actualizaciones deben ocurrir en orden de clasificación. Esto finalmente se reduce a la disciplina del código del colaborador individual que escribe el código, ya que tiene que asegurarse de que escribe y actualiza en el orden correcto dentro de una transacción.
  • Reducir la duración de escribe. La sabiduría habitual es la siguiente:al comienzo de la transacción, haga todas las lecturas (lea el estado existente), luego procese la lógica y calcule nuevos valores, luego escriba todas las actualizaciones al final de la transacción. Evite un patrón como 'leer->escribir->lógica->leer->escribir', en su lugar haga 'leer->leer->lógica->escribir->escribir'. Por supuesto, la verdadera artesanía consiste en cómo tratar casos reales, reales e individuales cuando aparentemente uno debe tiene que hacer escribe mid-transaction. Una nota especial aquí debe decirse acerca de un tipo específico de transacción:aquellas impulsadas por una cola, que por definición comienzan su actividad eliminando (=una escritura) de la cola. Estas aplicaciones siempre fueron notoriamente difíciles de escribir y propensas a errores (especialmente interbloqueos), afortunadamente hay formas de hacerlo, vea Usando tablas como colas .
  • Reduzca la cantidad de lecturas. Los escaneos de tablas son los causa más frecuente de interbloqueos. La indexación adecuada no solo eliminará los interbloqueos, sino que también puede mejorar el rendimiento en el proceso.
  • Aislamiento de instantáneas . Esto es lo más cercano que obtendrá a un almuerzo gratis en lo que respecta a evitar puntos muertos. Lo puse en último lugar intencionalmente, porque puede enmascarar otros problemas (como la indexación incorrecta) en lugar de solucionarlos.

Intentando resolver este problema con un LockCustomerByXXX enfoque me temo que no funciona. El bloqueo pesimista no escala. Simultaneidad optimista las actualizaciones son las camino a seguir si quieres tener algún tipo de rendimiento decente.