2008-10-30 7 views
4

Il y a un petit système, où une table de base de données sur la file d'attente MSSQL 2005. Plusieurs applications sont en train d'écrire à cette table, et une application est en train de lire et de traitement d'une manière FIFO.traitement parallèle de file d'attente de la base de données

je dois en faire un peu plus avancé pour être en mesure de créer un système distribué, où plusieurs applications de traitement peut fonctionner. Le résultat devrait être que l'application de traitement 2-10 devrait être capable de fonctionner et ils ne devraient pas interférer les uns les autres pendant le travail.

Mon idée est d'étendre la table de file d'attente avec une ligne indiquant qu'un processus travaille déjà là-dessus. L'application de traitement mettra d'abord à jour la table avec son idetifyer, puis demandera les enregistrements mis à jour.

donc quelque chose comme ceci:

start transaction 
update top(10) queue set processing = 'myid' where processing is null 
select * from processing where processing = 'myid' 
end transaction 

Après le traitement, il définit la colonne de traitement de la table à autre chose, comme « fini », ou autre chose.

J'ai trois questions à propos de cette approche.

Premièrement: cela peut-il fonctionner sous cette forme? Deuxièmement: si cela fonctionne, est-ce efficace? Avez-vous d'autres idées pour créer une telle distribution?

Troisième: En MSSQL le verrouillage est basée sur les lignes, mais après sont verrouillés une quantité de lignes, le verrou est étendu à toute la table. Ainsi, la deuxième application ne peut y accéder, jusqu'à ce que la première application ne libère pas la transaction. Quelle taille peut avoir la sélection (top x) pour ne pas verrouiller toute la table, ne créer que des verrous de ligne?

Répondre

6

Cela fonctionne, mais vous trouverez probablement vous tomberez dans le blocage ou les blocages lorsque de plusieurs processus essaient de lire/mettre à jour les mêmes données. J'ai écrit une procédure pour faire exactement cela pour l'un de nos systèmes qui utilise une sémantique de verrouillage intéressante pour assurer que ce type de chose fonctionne sans blocage ou interblocage, described here.

+0

C'est très bien, exactement ce dont j'ai besoin. Merci. – Biri

+0

Nice. J'ai dit que je serais intéressé ;-) – philsquared

+0

une chose à surveiller est un code non traité où un système supprime certaines informations mais se bloque/s'arrête avant de pouvoir traiter l'information. un délai d'attente avant de remettre en service le travail permettrait de résoudre ce problème mais peut devenir assez désordonné – mjallday

1

Cette approche me semble raisonnable, et est similaire à celle que j'ai utilisée dans le passé - avec succès.

En outre, la ligne/tableau ne seront verrouillés pendant la mise à jour et les opérations de sélection ont lieu, alors je doute la ligne vs question de table est vraiment une considération importante. À moins que le coût de traitement de votre application soit si faible qu'il soit négligeable, je garderais la valeur «supérieure» faible - peut-être juste 1. Bien sûr, cela dépend entièrement des détails de votre application.

Ceci étant dit, je ne suis pas un DBA, et ainsi sera également être intéressé par plus des réponses d'experts

1

En ce qui concerne votre question sur le verrouillage. Vous pouvez utiliser une touche de verrouillage pour le forcer à verrouiller des lignes seulement

update mytable with (rowlock) set x=y where a=b 
+0

Oui, je le sais, mais peu importe, après un certain temps, il passe au verrouillage de la table. Je suppose que cela dépend de la prise en compte de la vitesse: vaut-il la peine de verrouiller la table au lieu de conserver et gérer une liste de verrous de ligne. – Biri

+1

AFAIK rowlock est un indice. Cela ne force pas SQL à restreindre le verrouillage au niveau de la ligne, mais indique seulement qu'un verrou de ligne est préférable à un verrou de page ou un verrou de table. SQL va toujours se verrouiller à un verrou de table de verrouillage de page à sa propre discrétion. –

1

Le plus gros problème avec cette approche est que vous augmentez le nombre de « mises à jour » à la table. Essayez ceci avec un seul processus consommant (mise à jour + suppression) et d'autres insérant des données dans la table et vous constaterez qu'environ un million d'enregistrements, il commence à s'effondrer.

Je préférerais avoir un consommateur pour la DB et utiliser les files d'attente de messages pour fournir des données de traitement à d'autres consommateurs.

Questions connexes