¿Necesito una pista de actualización en este SP? Leer una fila de cola de datos más de una vez

StackOverflow https://stackoverflow.com/questions/8922797

Pregunta

Mi esquema DB es Job -> (muchos) JobData -> (muchos) resultados. Un trabajo se divide en múltiples filas de datos de trabajo para que múltiples hilos puedan procesar 'fragmentos' del trabajo (cada fila de datos de trabajo). Luego, las hilos de procesamiento inserta la (s) fila (s) de resultados para cada una de las redes de JobData que procesa.

Un solo hilo intenta leer los resultados en un bucle hasta que se leen todos los resultados. Tenga en cuenta que al mismo tiempo los hilos pueden estar procesando filas de JobData (hasta que se procesen todas) e insertando resultados. Entonces, en el bucle, cada llamada a este SP pasa en un JobKey ... pero de alguna manera con este código, los resultados se leen varias veces (muy baja frecuencia ... es decir, <3 filas por 8000 filas de resultados) pero solo reproducibles al azar.

Agregué un comentario a continuación en código junto a mi estado de cuenta de actualización con respecto a Updlock. Gracias por adelantado.

BEGIN TRANSACTION

-- Create a temp table TO store the select results
DECLARE @UnReadResults TABLE
(
    ResultKey uniqueidentifier
)

-- Wouldn't expect a UPDLOCK is needed since UPDATE statements create exclusive lock anyway?  Do I need to SELECT WITH UPDLOCK first, then do the UPDATE statement?

UPDATE TOP ( @pageSize ) Result
SET rResultRead = 1
OUTPUT INSERTED.rKey INTO @UnReadResults
FROM Result r INNER JOIN JobData AS jd ON jd.jdKey = r.rJobDataKey
WHERE jd.jdJobKey = @jobKey AND rResultRead = 0

-- Just return Job (always the same), JobData (could vary if chunk of result rows
-- spans multiple JobDatas) and Results that I successfully 'grabbed' by joining
-- to my temp table

SELECT j.jKey, j.jStatus, j.jResultsRead, 
   jd.jdKey, jd.jdJobKey, jd.jdDateStart, jd.jdDateComplete, jd.jdStatus,
   r.rKey, r.rProfileKey, r.rProfileAuthID, r.rResult, r.rReadLock, r.rReadAttempts
FROM Job j
    INNER JOIN JobData jd
        ON jKey = jdJobKey
    INNER JOIN Result r
        ON jdKey = rJobDataKey
    INNER JOIN @UnReadResults urr
        on rKey = urr.ResultKey

COMMIT TRANSACTION

Editar: Solo quería poner lo que tengo en su lugar ahora basado en la respuesta @GBN. Excluyendo todo el SP, pero la declaración de actualización ahora está formateada de tal manera:

UPDATE TOP ( @pageSize ) Result
SET rResultRead = 1, rReadLock = @lock, rReadAttempts = rReadAttempts + 1
OUTPUT INSERTED.rKey INTO @UnReadResults
FROM Result r WITH ( ROWLOCK, READPAST, UPDLOCK ) INNER JOIN JobData AS jd ON jd.jdKey = r.rJobDataKey
WHERE jd.jdJobKey = @jobKey AND rResultRead = 0

He estado funcionando con éxito ahora durante unos días, así que espero que clavé el problema. Si esto no parece un uso adecuado de los consejos de mesa, siéntase libre de avisarme.

No hay solución correcta

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top