# Shopify trasladou as reservas de inventario a MySQL

Published: 2026-10-10

Shopify trasladou o seu sistema de reserva de inventario de Redis á base de datos MySQL que xa contiña o libro maior de inventario. Un conxunto delimitado de filas de unidades individualmente bloqueables permite que as compras concurrentes usen SKIP LOCKED para seleccionar diferentes unidades elixibles. O deseño tamén depende dos límites das transaccións, o deseño da clave principal, as regras de reposición e a observación do tempo de retención da conexión durante a compra.

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

## Que abrangue este vídeo

- O antigo modelo de contador de cantidade de Redis xestionaba a concorrencia, pero a limpeza da reserva e a actualización do libro maior de MySQL non podían compartir unha única transacción atómica local.
- A substitución usa unha fila por unidade dispoñible nun conxunto limitado a 1.000 por combinación de artigo/localización. Un conxunto baleiro pode activar a reposición en liña con solicitudes concurrentes esperando detrás dun bloqueo de reposición.
- A clave principal composta é (shop\_id, inventory\_item\_id, inventory\_group\_id, id). Shopify reduciu a sobrecarga de bloqueo no seu prototipo e usou READ COMMITTED para evitar bloqueos de oco que bloqueaban a reposición.
- A reserva elimina as filas do conxunto antes de inserir os rexistros de reserva. A confirmación libera os bloqueos da base de datos mentres a retención almacenada persiste durante o pago; o pago exitoso reclama o libro maior e elimina a reserva nunha transacción atómica posterior.
- MySQL documenta SKIP LOCKED como unha vista inconsistente que omite as filas bloqueadas. Non establece un reconto completo de existencias nin unha quenda xusta, aplícase só a bloqueos a nivel de fila e non é seguro para a replicación baseada en declaracións.
- O exemplo de orixe inclúe expires\_at, pero Shopify non documenta o algoritmo de limpeza por caducidade de MySQL. A rama de liberación/caducidade do vídeo é un requisito explicativo do ciclo de vida.
- O tempo de retención da conexión noutro código de compra foi o pescozo de botella final no rendemento. Shopify escribiu en sombra ambos os sistemas, comparou os resultados e cambiou gradualmente cunha opción de retorno de emerxencia a Redis.

## Capítulos

- 0:00 Por que trasladar as reservas a MySQL?
- 0:29 Por que dous almacéns eran arriscados?
- 0:52 Cal se converte na unidade bloqueable?
- 1:15 Que ocorre cando o conxunto se baleira?
- 2:14 Que omite SKIP LOCKED?
- 2:26 Onde estaba o verdadeiro límite?
- 2:38 Por que enviaría este deseño?

## Transcrición traducida

Traducido da narración orixinal en inglés. O audio e os subtítulos dispoñibles son controlados por YouTube.

### Por que trasladar as reservas a MySQL?

0:00 Unha compra necesita que Redis sexa rápido. Shopify trasladou as reservas de inventario a MySQL usando unha fila por unidade nun conxunto delimitado. Por que elixir MySQL? Como se saltan os bloqueos de forma segura? Este é The Daily Diff, entre bastidores. E por que as consultas rápidas aínda atoparon un límite? Shopify é unha plataforma de comercio para vender en liña e en persoa. Redis é un almacén de datos en memoria.

0:21 MySQL é unha base de datos relacional, e Shopify xa gardaba o seu libro maior de inventario alí. Unha reserva mantén brevemente o stock mentres un comprador paga.

### Por que dous almacéns eran arriscados?

0:29 O seu modelo Redis decrementaba un contador de artigos. Reclamar unha orde pagada significaba actualizar o libro maior de MySQL e limpar Redis. Esas escrituras separadas podían deixar o stock vendido dúas veces ou non dispoñible cando debería ser vendible. O antigo modelo tamén carecía de coñecemento da localización. A substitución debe escoller o stock dalgún lugar que poida cumprir a orde. Un almacén no continente equivocado fai unha excelente entrada na base de datos e unha terrible promesa de entrega. Intentos anteriores de MySQL usaban unha fila de cantidade, polo que as compras competidoras facían cola no

### Cal se converte na unidade bloqueable?

0:56 mesmo bloqueo. Pense nunha corda de veludo arredor dunha cela de folla de cálculo. Engadir máis traballadores só alonga a cola. Shopify cambiou o obxecto bloqueable. Cada unidade dispoñible obtén a súa propia fila. Unha lectura de bloqueo salta as unidades que outra transacción ten e selecciona outras unidades elixibles. Diferentes traballadores poden adquirir diferentes filas, mentres o contador quente se mantén fóra do seu camiño.

### Que ocorre cando o conxunto se baleira?

1:15 Ese conxunto está limitado a mil filas por artigo e localización. A reposición extráese do libro maior. Se se baleira, a ruta de reserva repón en liña, con solicitudes competidoras esperando detrás dun bloqueo de reposición. Un conxunto baleiro non significa un almacén baleiro. A reserva elimina as filas do conxunto seleccionadas e despois insere os rexistros de reserva nunha transacción. A confirmación libera os bloqueos da base de datos.

1:35 A reversión desface os cambios. A reserva sobrevive ao procesamento do pago como estado almacenado. O pago exitoso reclama o libro maior e elimina a reserva atomicamente. Os bloqueos da base de datos nunca necesitan vixiar o formulario de pago. A súa clave principal composta comeza con tenda, artigo, grupo, despois a identidade da unidade. Coincidir coa busca reduciu o bloqueo de índices no seu prototipo. Tamén usan a lectura confirmada para evitar os bloqueos de oco que bloqueaban a

1:57 reposición do conxunto e unha orde de táboa consistente para evitar esperas circulares. O exemplo publicado rexistra un tempo de caducidade. Os pagos abandonados necesitan que o stock sexa liberado eventualmente, ou o carro da compra convértese nun propietario. A publicación de Shopify deixa ese algoritmo de limpeza sen especificar, polo que este diagrama mostra o requisito do ciclo de vida. Aquí está o truco.

### Que omite SKIP LOCKED?

2:14 Skip locked exclúe as filas bloqueadas, polo que o manual chama ao seu resultado unha vista inconsistente. Non proporciona nin un reconto completo de existencias nin unha quenda xusta. Manteña a decisión de dispoñibilidade e as regras de reposición arredor dela.

### Onde estaba o verdadeiro límite?

2:26 E ese límite? Outro código de compra estaba retendo as conexións á base de datos demasiado tempo. Shopify etiquetou os chamadores e mediu o tempo de retención da conexión, despois limpou a ruta de compra e revisou a concorrencia de fíos. As consultas rápidas aínda poden facer cola fóra da consulta.

### Por que enviaría este deseño?

2:38 Escribiron en sombra ambos os sistemas con Redis autoritario, compararon os resultados e despois cambiaron gradualmente cun interruptor de emerxencia. O meu veredicto é SHIP IT. Enviaríame o límite de transaccións compartido e esa implementación reversible, coa ruta de compra completa instrumentada. Tes algunha pregunta sobre isto? Ponla nos comentarios. E esa é a diferenza por hoxe.

2:54 Son Niko de Axrisi. Fusionar con responsabilidade.

## Fontes

- [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
