dba curso capacitacion sql sql-server tsql queue race-condition

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.