2009-02-18 6 views
12

Tengo un único proceso que consulta una tabla para registros donde PROCESS_IND = 'N', realiza algún proceso y luego actualiza el PROCESS_IND a 'Y'.Mejores prácticas para el procesamiento multiproceso de registros de base de datos

Me gustaría permitir que se ejecuten varias instancias de este proceso, pero no sé cuáles son las mejores prácticas para evitar problemas de concurrencia.

¿Dónde debería empezar?

+0

¿puede PROCESS_IND tener algún otro valor, como 'L'? – sfossen

+0

Claro, solo es usado por este proceso, por lo que puede ser cualquier cosa –

+0

Publicar el tamaño de página, la estructura de la tabla, #rows e índices ayudaría. – Vincent

Respuesta

9

El patrón que haría uso es el siguiente:

  • Crear columnas "lockedby" y "locktime", que son un/proceso/ID de la máquina de rosca y sello de tiempo, respectivamente (necesitará el ID de máquina cuando se divide el procesamiento entre varias máquinas)
  • Cada tarea sería hacer una consulta como:

    ACTUALIZACIÓN taskstable SET lockedby = (mi ID), locktime = NOW() DONDE lockedby ES ORDEN NULL ID del límite de 10

Donde 10 es el "tamaño de lote".

  • Entonces cada tarea hace un SELECT para saber qué filas se "bloqueado" para el procesamiento, y procesa los
  • Después de cada fila está completa, se establece lockedby y locktime volver a NULL
  • Todo esto es hecho en un bucle para tantos lotes como existen.
  • Un trabajo cron, o tarea programada, restablece periódicamente el "lockedby" de cualquier fila cuyo tiempo de bloqueo es demasiado largo, ya que presumiblemente se realizaron por una tarea que se colgó o se colgó. Alguien más los recogerá

El LIMIT 10 es específico de MySQL, pero creo que otras bases de datos tienen equivalentes. ORDER BY es import para evitar que la consulta sea no determinista.

+1

+1 para una muy buena idea. Simplemente no sé por qué el ORDER BY sería importante, a menos que haya un orden en el que se procesen las filas. De ser así, los procesos múltiples están fuera de discusión de todos modos. – mghie

+0

En Sybase puede usar "set rowcount {#rows | @variable}" para el tamaño de lote equivalente de LIMIT. – Vincent

+0

El ORDER BY solo es importante si necesita que sus sentencias SQL sean deterministas: en MySQL, esto es importante para reproducir el registro binario en modo de declaración, lo cual es vital para que funcione la replicación y la recuperación puntual. En otras bases de datos, es menos crucial. – MarkR

2

Debería habilitar row level locking sobre la mesa con:

CREATE TABLE mytable (...) LOCK DATAROWS 

continuación:

  • de comenzar la transacción
  • Seleccione su fila con FOR UPDATE opción (se bloquearlo)
  • Haz lo que quieras.

Ningún otro proceso puede hacer nada en esta fila hasta que finalice la transacción.

P. S. Algunos mencionan problemas de sobrecarga que pueden resultar del uso de LOCK DATAROWS.

Sí, hay gastos generales, aunque casi no llamaría un problema para una mesa como esta.

Pero si se cambia a DATAPAGES entonces puede bloquear una sola fila por PAGE (2k por defecto), y cuyos procesos filas residir en una página no va a ser capaz de ejecutar simultáneamente.

Si hablamos de tabla con una docena de filas que se bloquean a la vez, apenas habrá una disminución notable del rendimiento.

La concurrencia de procesos es de mucha más importancia para un diseño como ese.

+0

No conocemos suficiente información para realizar una llamada en 'tabla como esta', no conocemos el tamaño de página, cuántas filas por página, el tamaño de la tabla o estructura o qué otras consultas/procesos hay sobre la mesa. He visto aplicaciones traídas a sus necesidades por la implicación de significado de bloqueos de nivel de fila – Vincent

+0

Claro que no sabemos nada, pero hagamos una optimización prematura, por las dudas :) – Quassnoi

+0

No estoy seguro de lo que quiere decir? Pasar al bloqueo de nivel de fila de forma inmediata no es una optimización prematura. Solo se debe usar con moderación y, por lo general, solo cuando el código no se puede modificar y existen puntos muertos que no se pueden resolver de otras maneras. – Vincent

0

Convierta el procedimiento en una sola instrucción de SQL y procese varias filas como un único lote. Así es como se supone que funcionan las bases de datos.

+0

Sin embargo, hay muchos procesos que no se pueden ejecutar en el DB. – you786

1

La forma más obvia es bloquear, si su base de datos no tiene bloqueos, puede implementarlo usted mismo agregando un campo "Bloqueado".

Algunas de las formas de simplificar la simultaneidad es aleatorizar el acceso a los elementos no procesados, por lo que en lugar de competir en el primer elemento, distribuyen el acceso aleatoriamente.

4

Aunque entiendo la intención, no estoy de acuerdo con ir al nivel de fila de bloqueo inmediatamente. Esto reducirá su tiempo de respuesta y en realidad puede empeorar su situación. Si después de la prueba está viendo problemas de concurrencia con APL, primero debe realizar un movimiento iterativo hacia el bloqueo de la "página de datos".

Para responder a esta pregunta correctamente, se necesitaría más información sobre la estructura de la tabla y los índices involucrados, pero para seguir explicando.

DOL, el bloqueo de datarow usa mucho más bloqueos que el bloqueo de todas las páginas/nivel de página.La sobrecarga en la gestión de todos los bloqueos y, por lo tanto, la disminución de la memoria disponible debido a las solicitudes de más estructuras de bloqueo dentro de la memoria caché, disminuirá el rendimiento y contrarrestará las ganancias que pueda tener si adopta un enfoque más concurrente.

Pon a prueba tu enfoque sin mover primero en APL (bloqueo de todas las páginas 'por defecto') y luego, si se ven problemas, pasa a DOL (primero la página de datos y luego la datarow). Tenga en cuenta que cuando se cambia una tabla a DOL, todas las respuestas en esa tabla empeoran, la tabla usa más espacio y la tabla se vuelve más propensa a la fragmentación, lo que requiere un mantenimiento regular.

Así que, en resumen, no se mueva a datarows directamente intente su enfoque de concurrencia primero y luego si hay problemas use primero el bloqueo de páginas de datos y luego el último recurso.

Cuestiones relacionadas