Cela provoque un blocage car le UPDATE
query verrouille toutes les lignes de la table et, selon les index utilisés (ou leur absence), deux sessions différentes les verrouillent potentiellement dans un ordre légèrement différent. N'oubliez pas que UPDATE
, DELETE
, et SELECT ... FOR UPDATE
verrouillera toutes les lignes qu'ils rencontrent, que ces lignes correspondent à tous WHERE
conditions ou non. Ainsi, lorsque vous les utilisez, vous devez vous assurer qu'ils rencontrent le moins de lignes possible, en utilisant des index (idéalement la clé primaire) et en évitant les conditions vagues ou de sélection large.
Ma suggestion pour les files d'attente de travail est à peu près universelle :verrouillez le moins possible, aussi rarement que possible et toujours dans un ordre déterministe. Donc, généralement :
- Utilisez des lectures non bloquantes (
SELECT
standard ) pour trouver du travail à faire en recherchant des choses que votre travailleur sait faire et qui ne sont actuellement pas réclamées (lease_owner IS NULL AND lease_expiry IS NULL
-- ou similaire). - Choisissez un élément de travail (ou quelques-uns si vous osez, mais l'un d'entre eux est beaucoup plus simple et permet normalement des performances parfaitement acceptables).
- Mettez à jour votre élément de travail (pour le revendiquer, mais dans tous les cas, il doit également être mis à jour) :
- Ouvrir une transaction.
- Verrouillez l'élément de travail que vous avez choisi avec
SELECT ... FOR UPDATE
-- S'il n'est plus réclamé, abandonnez et choisissez-en un autre. - Mettez à jour l'élément de travail que vous avez choisi avec votre identifiant de travailleur et une date d'expiration pour votre bail.
- Validez votre transaction immédiatement.
- Commencez à travailler sur vos éléments de travail loués.
- Dans un autre processus, un autre observateur recherche les travaux abandonnés et les annule (via le même processus de mise à jour ci-dessus).
Vous pouvez facilement obtenir un débit très élevé avec cette conception (des milliers de travaux par seconde), et pratiquement sans conflit ni problème de commande. Les optimisations pour choisir un travail qui est moins susceptible d'entrer en conflit avec d'autres pollers sont simples et efficaces (par exemple, module sur Job ID ou similaire, choisi pour éviter la famine d'emplois). La clé est de se rappeler que le conflit sur la sélection d'emploi est ok -- il suffit d'abandonner et de réessayer et tout avance très vite.
Toutes les écritures de verrouillage pour les éléments/tâches de la file d'attente de travail doivent être effectuées uniquement sur des lignes uniques et par clé primaire uniquement .