Ai-je besoin d'un indice de mise à jour dans ce SP? Lire une ligne de file d'attente de données plus d'une fois

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

Question

Mon schéma de base de données est Job -> (beaucoup) jobdata -> (beaucoup) résultats. Un travail est pénétré en plusieurs lignes de travail afin que plusieurs threads puissent traiter les «morceaux» du travail (chaque ligne Jobdata). Ensuite, les threads de traitement insérer les lignes de résultat pour chacune des lignes de jobdata qu'elle traite.

Un seul fil tente de lire les résultats dans une boucle jusqu'à ce que tous les résultats soient lus. Notez qu'en même temps, les threads peuvent encore traiter les lignes de JobData (jusqu'à ce que tous soient traités) et l'insertion des résultats. Donc, dans la boucle, chaque appel à ce SP passe dans un ciel ... mais en quelque sorte avec ce code, les résultats sont lus plusieurs fois (très basse fréquence ... c'est-à-dire <3 lignes par 8000 lignes de résultats) mais seulement reproductibles au hasard.

J'ai ajouté un commentaire ci-dessous dans le code à côté de mon énoncé de mise à jour concernant le mise à jour. Merci d'avance.

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

Edit: Je voulais juste mettre ce que j'ai en place maintenant sur la base de @GBN. À l'exclusion de l'ensemble du SP, mais l'instruction de mise à jour est désormais formatée comme tel:

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

Je suis en cours d'exécution avec succès depuis quelques jours, alors j'espère que j'ai cloué le problème. Si cela ne ressemble pas à une utilisation appropriée des indices de table, n'hésitez pas à me le faire savoir.

Pas de solution correcte

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top