Міграції виконуються один раз на базу, а не на кожному сервері.
Як цього досягти:
- окремий крок деплою (job у CI, init-контейнер, release-фаза) замість
migrateу старті кожного контейнера; - якщо запускають з кожного сервера -
php artisan migrate --isolated --force: перший бере атомарне блокування в кеші, інші тихо завершуються. Кеш має бути спільним; --forceпотрібен, щоб команда не питала підтвердження на продакшені.
Сумісність схеми й коду. Під час rolling-деплою одночасно працюють стара й нова версії коду, тож міграція має підходити обом:
- Розширення: додати нову колонку (nullable чи з дефолтом), код пише в обидві.
- Перенесення даних фоново порціями.
- Перемикання коду на нову колонку.
- Звуження: видалити стару колонку окремим наступним релізом.
Що ще враховують:
- довгі блокування на великих таблицях:
instant()на MySQL,online()для індексів на PostgreSQL, нічні вікна для важкого; - PostgreSQL обгортає міграцію в транзакцію, а
CREATE INDEX CONCURRENTLYу транзакції не працює; - сідери довідників - окремо від міграцій і ідемпотентні.