2012-06-07 11 views
8

Tengo un proceso que se ejecuta con múltiples hilos.Bloqueos de inserción de tabla de base de datos desde una aplicación de múltiples hilos

El proceso tiene una colección segura de subprocesos de elementos para el proceso.

Cada subproceso procesa los elementos de la colección en un bucle.

Cada elemento de la lista se envía a un procedimiento almacenado por el hilo para insertar datos en 3 tablas en una transacción (en sql). Si una inserción falla, las tres fallan. Tenga en cuenta que el alcance de la transacción es por artículo.

Las inserciones son bastante simples, simplemente insertando una fila (relacionada con la clave externa) en cada tabla, con semillas de identidad. No hay lectura, solo inserte y luego avance al siguiente elemento.

Si tengo varios subprocesos que intentan procesar sus propios elementos y cada uno intenta insertarlos en el mismo conjunto de tablas, ¿esto creará interbloqueos, tiempos de espera o cualquier otro problema debido a bloqueos de transacciones?

Sé que tengo que usar una conexión db por hilo, me preocupan principalmente los niveles de bloqueo de las tablas en cada transacción. Cuando un hilo está insertando filas en las 3 tablas, ¿los otros hilos tendrán que esperar? No hay dependencia de filas por tabla, excepto que la identificación automática necesita ser incrementada. Si se trata de un bloqueo de nivel de tabla para incrementar la identidad, entonces supongo que otros hilos tendrán que esperar. Las inserciones pueden o no ser rápidas a veces. Si va a tener que esperar, ¿tiene sentido hacer subprocesamiento múltiple?

El objetivo del multihilo es acelerar el procesamiento de los artículos.

Por favor, comparta su experiencia.

PD: Identity seed no es un GUID.

+0

¿Son estos procedimientos almacenados realmente largos? – CodingGorilla

+0

¿Por qué no usa BULK INSERT? Esto ** realmente ** acelera el proceso de inserción. – Dennis

+0

No, solo estarán insertando y listo cuando se trata de la base de datos. No es un proceso pesado, en el peor caso digamos 10 segundos por transacción. En su mayoría, será como 1 o 2 segundos. –

Respuesta

4

En SQL Server, múltiples inserciones en una sola tabla normalmente no se bloquean entre sí. El mecanismo de generación de IDENTIDAD es altamente concurrente, por lo que no serializa el acceso. Las inserciones pueden bloquear entre sí si insertan la misma clave en un índice único (una de ellas también activará una violación de clave duplicada si ambas intentan comprometerse). También tiene un juego de probabilidad porque las claves son hash, pero solo entran en juego en transacciones grandes, consulte %%LOCKRES%% COLLISION PROBABILITY MAGIC MARKER: 16,777,215. Si la transacción se inserta en varias tablas tampoco debería haber conflictos siempre y cuando, una vez más, las claves insertadas sean disjuntas (esto sucede naturalmente si las inserciones son maestro-hijo-hijo).

Dicho esto, la presencia de índices secundarios y especialmente las limitaciones de claves externas puede introducir el bloqueo y posibles puntos muertos. Sin una definición de esquema exacta es imposible saber si eres o no susceptible de bloqueos. Cualquier otra carga de trabajo (informes, lecturas, mantenimiento) también se suma a los problemas de contención y puede provocar bloqueos y bloqueos.

despliegues muy muy muy de gama alta (el tipo que no necesita pedir consejos en los foros ...) pueden sufrir de síntomas del punto de inserción en caliente, consulte Resolving PAGELATCH Contention on Highly Concurrent INSERT Workloads

Por cierto, se hacen inserciones de múltiples hilos es muy rara vez la respuesta correcta para aumentar el rendimiento de la carga. Consulte The Data Loading Performance Guide para obtener un buen consejo sobre cómo resolver ese problema. Y un último consejo: los subprocesos múltiples rara vez son la respuesta para hacer que cualquier programa sea más rápido. La programación asíncrona es casi siempre la respuesta correcta. Ver AsynchronousProcessing y BeginExecuteNonQuery.

Como nota al margen:

simplemente insertando una fila (clave externa relacionada) en cada mesa, ... no hay lectura,

Esta declaración es en realidad contradice a sí mismo. Las claves foráneas implican lecturas, ya que deben validarse durante las escrituras.

+0

Gracias por muchas entradas y pistas. Los revisaré. En mi caso, el enhebrado es probablemente mejor que la asincronización solo porque mi objetivo no es finalizar el programa de llamada más rápido, sino tener datos en la base de datos lo más rápido posible. Hay otros procesos esperando por estos datos. Creo que esto será más rápido si hay, por ejemplo, 5 subprocesos que empujan datos en lugar de un subproceso que lo hace de forma asincrónica. Podría estar equivocado, pero por favor explica si piensas así. –

+0

Acepto la declaración "insertar, no leer". Quise decir que no tengo explícitamente ninguna otra operación de lectura ni nada en el medio, SQL Server tendrá que hacer lo suyo para verificar las claves externas. –

+1

En las plataformas de Windows, las aplicaciones de ayuno se escriben utilizando una cadena de agrupaciones de trabajadores (normalmente tantos subprocesos como núcleos disponibles) que * nunca * bloquean y realizan todas las operaciones asincrónicas. Consulte los documentos vinculados de [Programas de Windows de alto rendimiento] (http://rusanu.com/2008/11/11/high-performance-windows-programs/) .Net implemente esto para usted con el grupo de subprocesos administrados, todo lo que tiene hacer es jugar bien y usar métodos asíncronos. La biblioteca de Tareas y las nuevas construcciones ['await async'] (http://msdn.microsoft.com/en-us/library/hh191443 (v = vs.110) .aspx) lo hacen incluso más fácil de implementar. –

1

Los DBMS de servicio pesado como mssql son generalmente muy, muy buenos con la simultaneidad de manejo. Lo que sucederá exactamente con sus transacciones simultáneas de ejecución depende en gran medida de su nivel de TI (http://msdn.microsoft.com/en-us/library/ms175909%28v=sql.105%29.aspx), que puede establecer como mejor le parezca, pero en este escenario no creo que deba preocuparse por los bloqueos.

Ya sea que tenga sentido o no, siempre es difícil adivinar eso sin saber nada sobre su sistema. No es difícil probarlo, así que puedes descubrirlo tú mismo. Si tuviera que adivinar, diría que no te ayudará mucho si todos tus hilos van a estar haciendo insertar filas en una operación de contramarcha.

0

Los otros hilos esperarán de todos modos, su PC realmente no puede ejecutar más hilos que los núcleos de la CPU que tiene en cada momento dado.
Usted escribió que desea utilizar multi threading para acelerar el procesamiento. No estoy seguro de que esto sea algo que pueda tomar como dado/correcto de forma automática. El nivel de paralelismo y sus efectos sobre la velocidad de procesamiento depende de muchos factores, que dependen mucho del procesamiento, por ejemplo, si hay un IO involucrado, por ejemplo, o si se supone que cada hilo debe hacer solo en el procesamiento de la memoria. Esta es, creo, una de las razones por las que Microsoft ofrece los programadores de tareas en su marco tpl, y generalmente trata la concurencia de esta biblioteca como algo que se supone que debe establecerse en tiempo de ejecución.
Creo que su apuesta más segura es ejecutar consultas de prueba/procesos para ver exactamente qué sucede (aunque, por supuesto, todavía no será 100% exacto).También puede consultar las características optimisitc concurrency del servidor sql, que permiten el trabajo sin bloqueo (aunque no estoy seguro de cómo maneja las columnas de identidad)

2

¿Qué le hace pensar que tiene que ser un bloqueo de tabla si hay una identidad . No veo eso en ninguna de la documentación y acabo de probar un inserto con (rowlock) en una tabla con una columna de identidad y funciona.

Para minimizar el bloqueo, tome un candado. Para todos los procedimientos almacenados, actualice las tablas en el mismo orden.

¿Tiene inserciones en tres mesas que toman hasta 10 segundos cada una? Tengo algunas inserciones en las transacciones que golpean varias tablas (algunas de ellas grandes) y obtienen 100/segundo.

Revise el diseño y las teclas de su mesa. Si puede elegir un PK agrupado que represente el orden de su inserción y si puede ordenar antes de insertarlo, hará una gran diferencia. Revise la necesidad de cualquier otro índice. Si debe tener otros índices, supervise la fragmentación y la desfragmentación.

Relacionado pero no es lo mismo. Tengo un cargador de datos que debe analizar algunos datos y luego cargar millones de filas por noche pero no en una transacción. Se optimizó en 4 procesos paralelos comenzando con las tablas vacías, pero el problema fue que después de dos horas de carga el rendimiento se redujo en un factor de 10 debido a la fragmentación. Rediseñé las tablas para que el índice agrupado de PK estuviera en orden de inserción. Se eliminó cualquier otro índice que no produjo al menos un 50% de bache de selección. En la inserción nocturna, primero suelte (deshabilite) los índices y use solo dos hilos. Un hilo para analizar y otro para insertar. Luego recreo el índice al final de la carga. Obtuve una mejora de 100: 1 en 4 hilos martillando los índices. Sí, tienes un problema diferente pero revisa tus tablas. Con demasiada frecuencia creo que los índices se agregan para pequeños beneficios selectos sin considerar el golpe para insertar y actualizar. Además, el beneficio seleccionado a menudo se sobrevalora a medida que construye el índice y lo compara, y ese nuevo índice no tiene fragmentación.

+0

Lo siento, no quise decir que las inserciones tomarán 10 segundos cada una. Todavía estamos en la etapa de diseño y esta fue solo una cifra que arrojé en caso de que hubiera algún procesamiento adicional o espera, etc. Lo más probable es que sea instantánea. No hay otro índice en esta tabla, excepto el PK. Por lo tanto, otros escenarios no se aplicarán a mí. Pero es bueno saber que no hay un bloqueo de nivel de tabla para las inserciones de identidad. –

+0

Si se encuentra en la etapa de diseño, la multitracción es una optimización prematura. Debería poder obtener más de 100 minutos en un solo hilo. – Paparazzi

+0

Esperamos una gran cantidad de carga, por lo que solo estamos preparando con anticipación para ampliar. Podría ser un millón de registros a la vez que necesitan procesarse. ¡Entonces 100/seg todavía son 10,000 segundos, lo cual es mucho tiempo! –

Cuestiones relacionadas