Question

Il existe un petit système, où une table de base de données est mise en file d'attente sur MSSQL 2005. Plusieurs applications écrivent dans cette table et une application lit et traite les données de manière FIFO.

Je dois le rendre un peu plus avancé pour pouvoir créer un système distribué sur lequel plusieurs applications de traitement peuvent s'exécuter. Le résultat devrait être qu'une application de traitement 2-10 devrait pouvoir s'exécuter et qu'elle ne devrait pas s'immiscer pendant le travail.

Mon idée est d’étendre la table des files d’attente avec une ligne indiquant qu’un processus est déjà en cours de traitement. L’application de traitement mettra d’abord à jour la table avec son idetifyer, puis demandera les enregistrements mis à jour.

Donc, quelque chose comme ça:

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, la colonne de traitement de la table est définie sur autre chose, telle que "terminé" ou autre chose.

J'ai trois questions sur 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èmement: dans MSSQL, le verrouillage est basé sur les lignes, mais après le verrouillage d’un nombre de lignes, le verrou est étendu à l’ensemble de la table. La deuxième application ne peut donc pas y accéder tant que la première application ne libère pas la transaction. Quelle peut être la taille de la sélection (top x) pour ne pas verrouiller la table entière, créer uniquement des verrous de ligne?

Était-ce utile?

La solution

Cela fonctionnera, mais vous constaterez probablement que vous rencontrez des blocages ou des impasses où plusieurs processus tentent de lire / mettre à jour les mêmes données. J'ai écrit une procédure à suivre pour faire exactement cela pour l'un de nos systèmes, qui utilise une sémantique de verrouillage intéressante pour garantir que ce type de processus fonctionne sans blocage ni blocage, décrit ici .

Autres conseils

Cette approche me semble raisonnable et ressemble à celle que j'avais utilisée par le passé - avec succès.

De plus, la ligne / table ne sera verrouillée que pendant les opérations de mise à jour et de sélection. Je doute donc que la question ligne / table est vraiment un élément important à prendre en compte.

À moins que les frais généraux de traitement de votre application ne soient si minimes qu'ils soient négligeables, je garderais la mention "en haut". valeur faible - peut-être juste 1. Bien sûr, cela dépend entièrement des détails de votre application.

Cela dit, je ne suis pas un administrateur de base de données et je serai donc intéressé par d'autres réponses d'experts

.

En ce qui concerne votre question sur le verrouillage. Vous pouvez utiliser un indice de verrouillage pour le forcer à ne verrouiller que les lignes

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

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

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

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