J'ai une table dans MySQL qui représente une file d'attente de liens à traiter. Les liens sont traités par une application externe, un par un, et supprimés à la fin. Il s'agit d'une file d'attente à volume élevé et j'ai plusieurs instances de l'application de traitement, réparties sur plusieurs serveurs.
Comment puis-je m'assurer que chaque enregistrement est sélectionné par une seule application? Existe-t-il un moyen de signaler / verrouiller l'enregistrement?
En ce moment, pour éviter que deux ou plus ne récupèrent le même lien, je n'autorise chaque instance qu'à récupérer un certain ensemble d'enregistrements (basé sur le MOD de leur ID), mais ce n'est pas un moyen transparent d'augmenter le traitement de la file d'attente accélérer simplement en ajoutant de nouvelles instances.
Réponses:
Premièrement: MySQL est l'un des pires logiciels possibles pour l'implémenter, surtout s'il est très dynamique. La raison en est que les moteurs comme MEMORY et MyISAM n'ont que des verrous de table complète tandis que les moteurs plus appropriés comme InnoDB ont une pénalité en écriture plus élevée (pour fournir des propriétés ACID) et sont optimisés pour accéder aux enregistrements qui sont spatialement et temporellement proches (ceux-ci sont définis en mémoire ). Il n'y a pas non plus de bon système de notification de changement pour MySQL - il doit être implémenté comme un sondage. Il existe des dizaines de logiciels plus optimisés pour cette tâche .
Cela dit, j'ai vu avec succès mettre en œuvre ce type d'accès si les exigences de performance / efficacité ne sont pas très élevées. De nombreuses personnes ne peuvent pas se permettre d'introduire et de maintenir une technologie complète et distincte uniquement pour une petite partie de la logique métier.
SELECT FOR UPDATE
c'est ce que vous cherchez - lire la sérialisation. Bien qu'une MISE À JOUR / SUPPRIMER verrouille toujours la ligne pendant une transaction MYSQL en cours d'exécution, vous souhaiterez peut-être éviter une transaction volumineuse pendant le processus, donc:MySQL se chargera de verrouiller toutes les sélections simultanées sauf une lors de la sélection des lignes. Comme cela peut entraîner de nombreuses connexions verrouillées en même temps, gardez la transaction initiale aussi petite que possible et essayez de traiter plus d'une ligne à la fois.
la source
Comme je l'ai expliqué dans cet article , MySQL 8 a introduit la prise en charge de SKIP LOCKED et NO WAIT.
SKIP LOCKED est utile pour implémenter des files d'attente de travaux (alias files d'attente par lots) afin que vous puissiez ignorer les verrous déjà verrouillés par d'autres transactions simultanées.
NO WAIT est utile pour éviter d'attendre qu'une transaction simultanée libère les verrous que nous souhaitons également verrouiller. Sans NO WAIT, nous devons soit attendre que les verrous soient libérés (au moment de la validation ou de la libération par la transaction qui détient actuellement les verrous), soit que le délai d'acquisition des verrous expire. Par conséquent, NO WAIT agit comme un délai de verrouillage avec une valeur de
0
.Pour plus de détails sur SKIP LOCK et NO WAIT, consultez cet article .
la source
J'ai fait quelque chose de similaire avec des vérifications DBCC hors ligne (deux serveurs effectuant des restaurations de sauvegarde, puis une vérification DBCC). Un serveur rassemble toutes les 31 sauvegardes du serveur hier et les place dans une file d'attente, puis ce serveur et un autre tirent de cette file d'attente. Bien qu'il n'y ait pas beaucoup de serveurs, la méthode doit rester la même: demandez au serveur d'applications d'exécuter une requête de mise à jour par rapport à la file d'attente mettant à jour un champ de date / heure et un champ "serveur d'applications" avec le nom de ce serveur d'applications ou un ID encore meilleur numérique. Cela entraînera un verrouillage ou s'il existe déjà un verrou d'un autre serveur obtenant la ligne suivante, il sera bloqué et attendra que l'autre application ait fini d'obtenir la ligne suivante. Vous souhaiterez ensuite que l'application retire l'enregistrement le plus récent de la file d'attente pour son champ d'application et obtienne les informations que vous souhaitez. Utiliser MySQL '
la source