Створення базового профілю існуючої бази даних у Prisma без виконання команди migrate reset
Дізнайтеся, чому Prisma повідомляє про відхилення у існуючій базі даних, чому скидання під час міграції є неправильним рішенням, та як встановити базовий рівень за допомогою db pull, migrate diff та migrate resolve.
Програма Prisma Migrate працює з базою даних, яка вже містить таблиці та дані, і існує велика ймовірність того, що перший запуск команди npx prisma migrate dev завершиться попередженням про неузгодження та пропозицією скинути все. Це попередження означає, що база даних містить структуру, про яку її історія міграцій нічого не знає. Якщо погодитися, ваші дані будуть видалені. У цьому посібнику пояснюється, чому виникає конфлікт, чому скидання майже ніколи не є правильним рішенням для важливої бази даних, та як встановити базову схему, щоб Prisma використовувала її як вихідну точку та застосовувала зміни лише від неї.
Чому Prisma бачить конфлікт
Prisma Migrate зберігає два записи про еволюцію вашої схеми: файли міграцій у директорії prisma/migrations та таблицю під назвою _prisma_migrations у базі даних, яка вказує, які саме файли були застосовані. Коли ви запускаєте команду migrate dev, Prisma відтворює історію міграцій у тимчасовій базі даних та порівнює результат із справжньою.
Якщо у справжній базі даних вже є таблиці, які не були створені жодною міграцією — наприклад, тому що вона була створена вручну, іншим інструментом чи ранньою версією додатку — обидві бази не збігаються. Prisma називає це відхиленням. Оскільки migrate dev є командою для розробки, її стандартним рішенням є очищення бази даних та її перебудова на основі історії міграцій, тому вона пропонує скидання даних. Це доцільно для тимчасової локальної бази даних, але шкідливо для всього іншого.
Якщо ви хочете дізнатися більше про те, як база даних shadow бере участь у цьому порівнянні, перегляньте статтю про базу даних shadow Prisma та розбіжності в найменуваннях.
Чому migrate reset — це неправильне рішення
npx prisma migrate reset видаляє базу даних або кожну таблицю з її схеми, створює їх заново на основі ваших міграцій та запускає скрипти для насіння даних. Усі існуючі рядки втрачаються. У базі даних з реальними користувачами, замовленнями чи контентом це не вирішення конфліктів, а втрата даних.
Кращим підходом є залишити базу даних у спокої та оновити її відображення Prisma. Для цього потрібно зафіксувати поточну структуру як першу міграцію та повідомити Prisma, що ця міграція вже існує.
Етапи створення базового рівня поетапно
Крок 1: Дослідження існуючої бази даних
Виконайте команду npx prisma db pull. Prisma під’єднується до бази даних, читає її таблиці, стовпці, індекси та зв’язки, а потім записує відповідні моделі у файл schema.prisma. Після цього кроку файл схеми точно описує базу даних у її поточному стані.
Крок 2: Створення базової міграції без її застосування
Створіть папку для базового стану, наприклад prisma/migrations/0_init. Префікс 0_ дозволяє їй сортуватися перед усіма наступними міграціями з часовими позначками. Потім створіть SQL-код, який буде побудувати поточну схему з нуля, та збережіть його там за допомогою команди npx prisma migrate diff --from-empty --to-schema-datamodel prisma/schema.prisma --script > prisma/migrations/0_init/migration.sql. У новіших версіях Prisma параметр мети може називатися --to-schema, тому перевірте документацію до вашої версії за допомогою команди npx prisma migrate diff --help.
Цей крок є важливим, оскільки він створює файл міграції, не торкаючись бази даних. Поширеною помилкою є виконання команди npx prisma migrate dev --name baseline на цьому етапі. У випадку бази даних, яка вже має таблиці та не має історії міграцій, ця команда виявляє ту саму відхилення, що й раніше, та пропонує знову скинути налаштування, що саме й потрібно уникнути. SQL-код базового стану ніколи не слід виконувати проти існуючої бази даних, оскільки її таблиці вже існують.
Крок 3: Позначити базовий стан як застосований
Виконайте команду npx prisma migrate resolve --applied 0_init. Аргументом є назва папки з міграціями. Якщо папка була створена з часовим позначенням, наприклад 20250101120000_baseline, необхідно вказати саме цю повну назву, а не просто baseline.
Ця команда не виконує жодних запитів SQL до ваших таблиць. Вона додає рядок у _prisma_migrations, який свідчить про те, що базовий стан застосований. Фактично ви змінюєте записи Prisma так, щоб він вважав поточну структуру наміреною та коректною.
Як це вирішує конфлікт
Це схоже на конфлікт при злитті в Git: коли ваша гілка не має комітів, які вже є у головній гілці, ви оновлюєте саму гілку замість того, щоб видаляти головну. Тут база даних випереджає, і ви оновлюєте історію Prisma до її рівня.
Після запису базового стану наступна команда npx prisma migrate dev відтворює операцію 0_init у «тіньовій» базі даних, отримує таку саму структуру, як і у реальній базі даних, та не виявляє жодних відхилень. Відтепер, коли ви змінюєте файл schema.prisma, Prisma генерує нову міграцію, яка містить лише відмінності, та застосовує саме їх.
Чому це важливо для великих баз даних
Використання базового рівня є найефективнішим, коли база даних містить велику кількість інформації. Оскільки базовий рівень зберігається у _prisma_migrations, а схема відповідає діючій базі даних, Prisma не торкається існуючих таблиць та рядків, а застосовує лише нові зміни, тож ваша таблиця users залишається недоторканою.
Запам’ятайте кілька практичних порад:
- Виконайте команду
migrate resolve --appliedодин раз для кожного існуючого середовища, такого як staging та production, адже кожна база даних має власну таблицю_prisma_migrations. - У середовищі production застосовуйте пізніші міграції за допомогою команди
npx prisma migrate deploy, а неmigrate dev, оскільки остання призначена лише для розробки. - Збережіть папку з базовим рівнем у системі контролю версій, щоб усі розробники та завдання CI мали однакову вихідну точку.
Основні висновки
- Попередження про зміщення в існуючій базі даних означає, що історія міграцій Prisma відсутня, а не те, що база даних пошкоджена.
- Скидання даних призводить до їх видалення; використовуйте цей інструмент лише для тимчасових локальних баз даних.
- Встановіть базовий рівень шляхом аналізу за допомогою
db pull, створення SQL-запитів за допомогоюmigrate diff --from-emptyта їх запису за допомогоюmigrate resolve --applied. - Не використовуйте
migrate devдля створення базового рівня на заповненій базі даних, оскільки це також спричиняє запит на скидання даних. - Після встановлення базового рівня Prisma керує лише інкрементальними змінами, а існуючі дані залишаються недоторканими.