Главная / Статьи / Создание базового состояния существующей базы данных в Prisma без выполнения команды migrate reset

Создание базового состояния существующей базы данных в Prisma без выполнения команды migrate reset

Узнайте, почему Prisma фиксирует отклонения в существующей базе данных, почему сброс миграций — неверное решение, и как установить базовый уровень с помощью db pull, migrate diff и migrate resolve.

1029 слов

Prisma Migrate работает с базой данных, в которой уже есть таблицы и данные, и с высокой вероятностью первая команда npx prisma migrate dev завершится предупреждением о несоответствии структуры и предложит сбросить всё. Это сообщение означает, что в базе данных присутствует структура, о которой миграционная история Prisma ничего не знает. Если согласиться на сброс, данные будут удалены. В этом руководстве объясняется, почему возникает конфликт, почему сброс практически никогда не является правильным решением для важной базы данных, и как задать основу существующей схемы, чтобы 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 по крайней мере один раз для каждой существующей среды, такой как стадионная и производственная, поскольку у каждой базы данных есть своя таблица _prisma_migrations.
  • В производственной среде применяйте более поздние миграции с помощью команды npx prisma migrate deploy, а не migrate dev, предназначенной исключительно для разработки.
  • Загрузите папку с базовым состоянием в систему контроля версий, чтобы все разработчики и задачи CI использовали одну и ту же отправную точку.

Основные выводы

  • Предупреждение о смещении в существующей базе данных означает отсутствие истории миграций Prisma, а не ошибку в самой базе данных.
  • Сброс удаляет данные; рассматривайте этот инструмент только как средство для временных локальных баз данных.
  • Определение исходного состояния осуществляется путем анализа с помощью db pull, генерации SQL-кодов с помощью migrate diff --from-empty и записи результата с помощью migrate resolve --applied.
  • Не используйте migrate dev для создания исходного состояния на уже заполненной базе данных, так как это вызовет тот же запрос на сброс.
  • После установления исходного состояния Prisma обрабатывает только дополнительные изменения, при этом существующие данные остаются нетронутыми.