curso - Condición de carrera de SQL Server Process Queue
curso dba sql server (2)
Tengo una cola de pedidos a la que acceden varios procesadores de órdenes a través de un procedimiento almacenado. Cada procesador transfiere una identificación única que se utiliza para bloquear las siguientes 20 órdenes para su propio uso. El procedimiento almacenado luego devuelve estos registros al procesador de la orden sobre la que se actuará.
Hay casos en que múltiples procesadores pueden recuperar el mismo registro ''OrderTable'' y en ese momento intentan operarlo simultáneamente. Esto, en última instancia, da lugar a errores lanzados más adelante en el proceso.
Mi siguiente línea de acción es permitir que cada procesador tome todas las órdenes disponibles y simplemente haga un ciclo completo de los procesadores, pero esperaba simplemente hacer esta sección del hilo de código segura y permitir a los procesadores tomar los registros cuando lo deseen.
Explicitamente: cualquier idea de por qué estoy experimentando esta condición de carrera y cómo puedo resolver el problema.
BEGIN TRAN
UPDATE OrderTable WITH ( ROWLOCK )
SET ProcessorID = @PROCID
WHERE OrderID IN ( SELECT TOP ( 20 )
OrderID
FROM OrderTable WITH ( ROWLOCK )
WHERE ProcessorID = 0)
COMMIT TRAN
SELECT OrderID, ProcessorID, etc...
FROM OrderTable
WHERE ProcessorID = @PROCID
Editar:
Busqué en Google para verificar mi respuesta: "Procesamiento de colas de datos en SQL Server con READPAST y UPDLOCK" . Han pasado años desde que leí y jugué con esta solución.
Original:
Si usa la sugerencia de READPAST, las filas bloqueadas se saltan. Has usado ROWLOCK, por lo que deberías evitar la escalada de bloqueo. También necesita UPDLOCK, como descubrí.
Entonces el proceso 1 bloquea 20 filas, el proceso 2 tomará los siguientes 20, el proceso 3 toma las filas 41 a 60, etc.
La actualización también se puede escribir así:
UPDATE TOP (20)
foo
SET
ProcessorID = @PROCID
FROM
OrderTable foo WITH (ROWLOCK, READPAST, UPDLOCK)
WHERE
ProcessorID = 0
Refrescar, oct 2011
Esto se puede hacer de forma más elegante con la cláusula OUTPUT si necesita un SELECT y una ACTUALIZACIÓN de una vez.
Puede usar Service Broker. También puedes usar sp_getapplock para serializar el acceso a tus filas, eso eliminará las condiciones de carrera:
"Asistir a la concurrencia mediante la creación de sus propios bloqueos (Mutex en SQL)" http://sqlblogcasts.com/blogs/tonyrogerson/archive/2006/06/30/855.aspx