# Shopify a déplacé les réservations d'inventaire dans MySQL

Published: 2026-10-10

Shopify a déplacé son système de réservation d'inventaire de Redis vers la base de données MySQL qui contenait déjà le registre d'inventaire. Un pool borné de lignes unitaires verrouillables individuellement permet aux caisses concurrentes d'utiliser SKIP LOCKED pour sélectionner différentes unités éligibles. La conception dépend également des limites de transaction, de la disposition de la clé primaire, des règles de réapprovisionnement et de l'observation du temps de maintien de la connexion lors du paiement.

Canonical: https://thedailydiff.dev/fr-CA/video/shopify-reservation-locks/

## Ce que cette vidéo couvre

- L'ancien modèle de compteur de quantité Redis gérait la concurrence, mais le nettoyage des réservations et la mise à jour du registre MySQL ne pouvaient pas partager une seule transaction atomique locale.
- Le remplacement utilise une ligne par unité disponible dans un pool plafonné à 1 000 par combinaison article/emplacement. Un pool vide peut déclencher un réapprovisionnement en ligne avec des requêtes concurrentes en attente derrière un verrou de réapprovisionnement.
- La clé primaire composite est (shop\_id, inventory\_item\_id, inventory\_group\_id, id). Shopify a réduit la surcharge de verrouillage dans son prototype et a utilisé READ COMMITTED pour éviter les verrous d'intervalle qui bloquaient le réapprovisionnement.
- La réservation supprime les lignes du pool avant d'insérer les enregistrements de réservation. La validation libère les verrous de la base de données pendant que la retenue stockée persiste pendant le paiement ; un paiement réussi revendique le registre et supprime la réservation dans une transaction atomique ultérieure.
- MySQL documente SKIP LOCKED comme une vue incohérente qui omet les lignes verrouillées. Il n'établit pas un décompte complet des stocks ni un tour de rôle équitable, s'applique uniquement aux verrous au niveau des lignes et est dangereux pour la réplication basée sur les instructions.
- L'exemple source inclut expires\_at, mais Shopify ne documente pas l'algorithme de nettoyage de l'expiration de MySQL. La branche de libération/expiration de la vidéo est une exigence de cycle de vie explicative.
- Le temps de maintien de la connexion dans d'autres codes de paiement était le dernier goulot d'étranglement du débit. Shopify a écrit en mode fantôme les deux systèmes, comparé les résultats et est passé progressivement avec un mécanisme de secours Redis.

## Chapitres

- 0:00 Pourquoi déplacer les réservations dans MySQL ?
- 0:29 Pourquoi deux magasins étaient-ils risqués ?
- 0:52 Quelle est l'unité verrouillable ?
- 1:15 Que se passe-t-il lorsque le pool se vide ?
- 2:14 Qu'est-ce que SKIP LOCKED omet ?
- 2:26 Où était le vrai plafond ?
- 2:38 Pourquoi expédier cette conception ?

## Transcription traduite

Traduit de la narration originale en anglais. L'audio et les sous-titres disponibles sont contrôlés par YouTube.

### Pourquoi déplacer les réservations dans MySQL ?

0:00 Un paiement a besoin de Redis pour rester rapide. Shopify a déplacé les réservations d'inventaire dans MySQL en utilisant une ligne par unité dans un pool borné. Pourquoi choisir MySQL ? Comment ignorer les verrous en toute sécurité ? Ceci est The Daily Diff, dans les coulisses. Et pourquoi les requêtes rapides atteignaient-elles toujours un plafond ? Shopify est une plateforme de commerce pour la vente en ligne et en personne. Redis est un magasin de données en mémoire.

0:21 MySQL est une base de données relationnelle, et Shopify y conservait déjà son registre d'inventaire. Une réservation retient brièvement le stock pendant qu'un acheteur paie.

### Pourquoi deux magasins étaient-ils risqués ?

0:29 Leur modèle Redis décrémentait un compteur d'articles. Réclamer une commande payée signifiait mettre à jour le registre MySQL et nettoyer Redis. Ces écritures séparées pouvaient laisser du stock vendu deux fois ou indisponible alors qu'il devrait être vendable. L'ancien modèle manquait également de connaissance de l'emplacement. Le remplacement doit choisir le stock d'un endroit qui peut exécuter la commande. Un entrepôt sur le mauvais continent fait une excellente entrée de base de données et une terrible promesse de livraison. Les tentatives précédentes de MySQL utilisaient une ligne de quantité, de sorte que les paiements concurrents faisaient la queue au

### Quelle est l'unité verrouillable ?

0:56 même verrou. Pensez à une corde en velours autour d'une cellule de feuille de calcul. L'ajout de travailleurs ne fait qu'allonger la file d'attente. Shopify a changé l'objet verrouillable. Chaque unité disponible obtient sa propre ligne. Une lecture de verrouillage ignore les unités qu'une autre transaction détient et sélectionne d'autres unités éligibles. Différents travailleurs peuvent acquérir différentes lignes, tandis que le compteur chaud reste hors de leur chemin.

### Que se passe-t-il lorsque le pool se vide ?

1:15 Ce pool est borné à mille lignes par article et emplacement. Le réapprovisionnement puise dans le registre. S'il se vide, le chemin de la réserve se réapprovisionne en ligne, avec des requêtes concurrentes en attente derrière un verrou de réapprovisionnement. Un pool vide ne signifie pas un entrepôt vide. La réservation supprime les lignes de pool sélectionnées, puis insère les enregistrements de réservation dans une transaction. Le commit libère les verrous de la base de données.

1:35 Le rollback annule les modifications. La réservation survit au traitement du paiement comme état stocké. Un paiement réussi revendique le registre et supprime la réservation atomiquement. Les verrous de la base de données n'ont jamais besoin de surveiller le formulaire de paiement. Leur clé primaire composite commence par le magasin, l'article, le groupe, puis l'identité de l'unité. La correspondance de la recherche a réduit le verrouillage des index dans leur prototype. Ils utilisent également la lecture validée pour éviter les verrous d'intervalle qui bloquaient le réapprovisionnement du pool,

1:57 et un ordre de table cohérent pour éviter les attentes circulaires. L'exemple publié enregistre une heure d'expiration. Les paiements abandonnés nécessitent que le stock soit finalement libéré, ou le panier d'achat devient un propriétaire. La publication de Shopify laisse cet algorithme de nettoyage non spécifié, donc ce diagramme montre l'exigence du cycle de vie. Voici le problème.

### Qu'est-ce que SKIP LOCKED omet ?

2:14 Skip locked exclut les lignes verrouillées, donc le manuel appelle son résultat une vue inconsistante. Il n'offre ni un décompte complet des stocks ni une prise de tour équitable. Gardez la décision de disponibilité et les règles de réapprovisionnement autour d'elle.

### Où était le vrai plafond ?

2:26 Et ce plafond ? D'autres codes de paiement maintenaient les connexions à la base de données trop longtemps. Shopify a tagué les appelants et mesuré le temps de maintien de la connexion, puis a nettoyé le chemin de paiement et a revu la concurrence des threads. Les requêtes rapides peuvent toujours faire la queue en dehors de la requête.

### Pourquoi expédier cette conception ?

2:38 Ils ont écrit en mode fantôme les deux systèmes avec Redis faisant autorité, ont comparé les résultats, puis ont commuté progressivement avec un interrupteur d'arrêt d'urgence. Mon verdict est SHIP IT. J'expédierais la limite de transaction partagée et ce déploiement réversible, avec tout le chemin de paiement instrumenté. Vous avez une question à ce sujet ? Mettez-la dans les commentaires. Et c'est tout pour The Daily Diff aujourd'hui.

2:54 Je suis Niko d'Axrisi. Fusionnez de manière responsable.

## Sources

- [We replaced Redis with MySQL for inventory reservations—and it scaled](https://shopify.engineering/scaling-inventory-reservations) — Shopify Engineering — Emilie Noel
- [Simplified reservation SQL embedded in Shopify's article](https://gist.github.com/CourtneySymons/cb5ecbe86331047aae166d5b1f1d555c) — Shopify Engineering / CourtneySymons on GitHub Gist
- [MySQL 8.0 — Locking Reads](https://dev.mysql.com/doc/refman/8.0/en/innodb-locking-reads.html) — Oracle / MySQL Reference Manual
- [MySQL 8.0 — Transaction Isolation Levels](https://dev.mysql.com/doc/refman/8.0/en/innodb-transaction-isolation-levels.html) — Oracle / MySQL Reference Manual
- [What Is Shopify and How Does It Work?](https://www.shopify.com/blog/what-is-shopify) — Shopify
- [Redis quick starts](https://redis.io/docs/latest/develop/get-started/) — Redis documentation
- [What is MySQL?](https://dev.mysql.com/doc/refman/8.0/en/what-is-mysql.html) — Oracle / MySQL Reference Manual
