Processus SQL Server Race Condition file d'attente
-
06-09-2019 - |
Question
I ai une file d'attente de commandes qui est accessible par plusieurs processeurs de commande par le biais d'une procédure stockée. Chaque processeur passe un identifiant unique qui est utilisé pour verrouiller les 20 prochaines commandes pour son propre usage. La procédure stockée retourne ensuite ces enregistrements au processeur afin d'y donner suite.
Il y a des cas où plusieurs processeurs sont en mesure de récupérer le même enregistrement « OrderTable » à quel point ils essaient de fonctionner simultanément sur elle. Il en résulte finalement des erreurs jetés plus tard dans le processus.
Mon prochain cours de l'action est de permettre à chaque grab processeur toutes les commandes disponibles et se trouve juste robin des processeurs, mais j'espérais simplement faire cette section de fil de code sûr et permettre aux processeurs de saisir des enregistrements chaque fois qu'ils aiment.
Explicitement -. Toute idée pourquoi je fais l'expérience de cette condition de course et comment je peux résoudre le problème
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
La solution
Edit:
Je googlé pour vérifier ma réponse: "Queues de traitement de données dans SQL Server avec READPAST et UPDLOCK « . Cela fait des années que je lu et joué avec cette solution.
Original:
Si vous utilisez la touche READPAST, puis lignes verrouillées sont ignorées. Vous avez utilisé ROWLOCK de sorte que vous devriez éviter l'escalade de verrous. Vous devez également UPDLOCK, comme je l'ai découvert.
Processus 1 verrous 20 rangs, deux processus prennent la 20 suivante, le processus prend trois lignes 41 à 60, etc
La mise à jour peut également être écrit comme ceci:
UPDATE TOP (20)
foo
SET
ProcessorID = @PROCID
FROM
OrderTable foo WITH (ROWLOCK, READPAST, UPDLOCK)
WHERE
ProcessorID = 0
Actualiser, octobre 2011
Cela peut se faire de façon plus élégante avec la clause de sortie si vous avez besoin d'un SELECT et UPDATE en une seule fois.
Autres conseils
Vous pouvez utiliser Service Broker. Vous pouvez également utiliser sp_getapplock pour sérialiser l'accès à vos lignes - qui éliminera les conditions de course:
"Aider Concurrency en créant vos propres Locks (mutexs dans SQL)" http://sqlblogcasts.com/blogs/tonyrogerson/archive/2006 /06/30/855.aspx