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
Était-ce utile?

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

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