2011-11-04 3 views
0

J'ai plus de 5 processus simultanément sélectionnant des lignes de la même table mysql. Chaque processus sélectionne 100 lignes, PROCESS IT IT et SUPPRIME les lignes sélectionnées.
Comment atomique sélectionner des lignes dans Mysql?

Mais je reçois la même ligne sélectionnée et traitée 2 fois ou plus. Comment puis-je l'éviter du côté MYSQL ou Ruby on Rails?

L'application est construite sur Ruby On Rails ...

Répondre

4

Votre table semble être un flux de travail, ce qui signifie que vous devriez avoir un champ indiquant l'état de la rangée ("revendiquée", dans votre cas). Les autres processus doivent être sélectionnés pour les lignes non réclamées, ce qui empêchera les processus d'avancer sur les lignes des autres.

Si vous voulez prendre un peu plus loin, vous pouvez utiliser des identifiants de processus afin que vous sachiez ce qui fonctionne sur ce, et peut-être combien de temps est trop long pour travailler, et que ce soit fini, etc.

Et oui, revenez à vos anciennes questions et approuvez quelques réponses. J'ai vu au moins un que vous avez certainement manqué.

3

La réponse d'Eric est bon, mais je pense que je devrais dire un peu plus ...

Vous avez des colonnes supplémentaires dans votre table disent:

lockhost VARCHAR(60), 
lockpid INT, 
locktime INT, -- Or your favourite timestamp. 

tous les Default NULL.

Ensuite, vous avez les processus de travail "réclamation" les lignes en faisant:

UPDATE tbl SET lockhost='myhostname', lockpid=12345, 
locktime=UNIX_TIMESTAMP() WHERE lockhost IS NULL ORDER BY id 
LIMIT 100 

Ensuite, vous traitez les lignes revendiquées avec SELECT ... WHERE lockhost = 'myhostname' et lockpid = 12 345

Après avoir terminé le traitement d'une ligne, vous effectuez les mises à jour nécessaires et définissez lockhost, lockpid et locktime sur NULL (ou supprimez-le).

Cela arrête la même ligne traitée par plusieurs processus à la fois. Vous avez besoin du nom d'hôte, car vous pouvez avoir plusieurs hôtes en cours de traitement.

Si un processus se bloque alors qu'il traite un lot, vous pouvez vérifier si la colonne "locktime" est très ancienne (beaucoup plus ancienne que le traitement peut éventuellement prendre, disons plusieurs heures). Ensuite, vous pouvez simplement récupérer certaines lignes qui ont un ancien "locktime" même si leur lockhost n'est pas nul.

Il s'agit d'un "modèle de file d'attente" assez courant dans les bases de données; ce n'est pas extrêmement efficace. Si vous avez un taux très élevé d'éléments entrant/sortant de la file d'attente, pensez à utiliser un serveur de file d'attente approprié à la place.

Questions connexes