Même si ce n'est pas la meilleure solution, comme je ne sais pas comment ignorer les lignes verrouillées, j'en sélectionne une aléatoire et j'essaie d'obtenir un verrou.
START TRANSACTION;
SET @v1 =(SELECT myId FROM tests.table WHERE status is NULL LIMIT 1);
SELECT * FROM tests.table WHERE [email protected] FOR UPDATE; #<- lock
Définition d'un petit délai d'attente pour la transaction, si cette ligne est verrouillé la transaction est annulée et j'essayer un autre. Si j'obtiens le verrou, je le traite. Si (malchance) cette ligne était verrouillée, elle est traitée et le verrou est libéré avant mon délai d'attente, puis je sélectionne une ligne qui a déjà été «traitée»! Cependant, je vérifie un champ que mes processus ont défini (par exemple, statut): si l'autre transaction de processus s'est terminée correctement, ce champ me dit que le travail a déjà été fait et que je ne traite plus cette ligne. Toute autre solution possible sans transaction (par exemple, en définissant un autre champ si la ligne n'a pas d'état et ... etc.) peut facilement fournir des conditions de concurrence et des processus manqués (par exemple, un thread meurt brusquement, les données allouées sont toujours balisées, alors qu'une transaction arrive à expiration, réf. commentaire here
Hope it helps
1 en utilisant LIMIT est une bonne idée –
Dans cet exemple, si le script brusquement interrompu après la première mise à jour, comment voulez-vous « nettoyer » la. base de données de vieux processus? Sinon, ces 100 lignes ne seraient jamais pris en charge –
Bonne question. Je règle habituellement soit la même colonne ou un ' colonne 'state' pour indiquer la réussite (dans le cadre de la transaction). Ensuite, si un processus meurt, vous pouvez définir n'importe quel process_id pour un processus non existant à NULL pour un autre processus à ramasser. Je préfère les tâches cron pour le nettoyage, mais vous pouvez également faire partie de démarrer un nouveau processus. –