Статьи

Ошибка пролетного пути: найдены непустые схемы без таблицы истории схемы

Постановка задачи

Мы столкнулись с ошибкой Flyway при попытке развернуть некоторые новые изменения схемы в существующей базе данных. Это был микросервис Java, использующий Jenkins в качестве инструмента CI / CD для развертывания. Конвейер сборки не смог развернуть изменения схемы в нашей среде Test / DevQA, поскольку он не смог подключиться к Eureka.

Когда мы просмотрели журналы в SumoLogic, мы обнаружили несколько ошибок, зарегистрированных приложением, указывающих на проблемы с Flyway:

Ошибка запуска приложения Ошибка создания компонента с именем «flywayInitializer», определенным в ресурсе пути к классу. Ошибка вызова метода init; Вложенное исключение — org.flywaydb.core.api.FlywayException: найдены непустые схемы без таблицы истории схемы! Используйте baseline () или установите для baselineOnMigrate значение true, чтобы инициализировать таблицу истории схемы.

"source":"stdout", 
"level":"ERROR", 
"message":"Application startup failed", 
"logger":"org.springframework.boot.SpringApplication", 
"thread":"main", 
"class":"org.springframework.boot.SpringApplication", 
"exception":"org.springframework.beans.factory.BeanCreationException"

Случай использования

Читая подробности ошибки / трассировки стека, я смог понять, что здесь происходит. С микросервисом уже была связана база данных, и она была развернута во всех средах. Flyway не использовался для развертывания начальных изменений схемы, и казалось, что развертывание базы данных было сделано вручную.

В качестве наилучшей практики мы пытаемся использовать Flyway в качестве среды миграции базы данных для выполнения сценариев DDL и DML для наших микросервисов Java. Это вызвало ошибку запуска приложения, так как во время развертывания Flyway обнаружил непустые схемы без таблицы истории схемы.

Давайте посмотрим подробнее, как работает Flyway, чтобы лучше это понять.

Как работает Flyway?

Если вы хотите раскрутить новый экземпляр БД в другой среде, Flyway может сделать это для вас на одном дыхании. При запуске приложения оно пытается установить соединение с базой данных. Он выдаст ошибку, если не сможет.

Он помогает вам легко развивать схему базы данных и надежен во всех случаях. Нет необходимости выполнять сценарии базы данных вручную.

Каждый раз, когда возникает необходимость обновить базу данных, будь то схема (DDL) или справочные данные (DML), вы можете просто создать новый сценарий миграции с номером версии, превышающим текущий. Когда Flyway запускается, он находит новый скрипт и соответственно обновляет базу данных.

Flyway сканирует файловую систему и сортирует их по номеру версии.

Flyway создает имя таблицы schema_version в вашей базе данных. Эта таблица отвечает за отслеживание состояния базы данных и ведет явную запись для различных выполненных сценариев SQL. По мере применения каждой миграции таблица истории схемы обновляется.

разрешение

Поскольку мы пытались внести изменения в схему, внедрив Flyway в уже существующую базу данных, содержащую таблицу, возникла ошибка приложения. В базе данных нет существующей таблицы schema_version, поэтому Flyway не смог отследить состояние базы данных и выполнить правильные сценарии SQL из репозитория приложения.

Однако, если бы не было существующей базы данных, и мы впервые строили схему с нуля, это не было бы проблемой. Flyway успешно создал бы базу данных и выполнил бы изменения схемы.

Поскольку это приложение уже запущено в производственной среде, удаление таблицы, разрешение Flyway воссоздать новую таблицу и таблицу ‘схема-версия’ и заполнение данных в существующей таблице выходит за рамки.

Таким образом, мы должны были найти способ проинформировать Flyway, что он имеет дело с базой данных с существующими таблицами. Вы можете сделать это, явно установив для свойства flyline baseline-on-migrate значение True в файле application.yml.

flyway: 
enabled: true 
schemas: EmployeeHistory 
locations: classpath:/sql

flyway.baseline-on-migrate: true

Из документации Flyway :

# Whether to automatically call baseline when migrate is executed against a non-empty schema with no schema history table. 
# This schema will then be initialized with the baselineVersion before executing the migrations. 
# Only migrations above baselineVersion will then be applied. 
# This is useful for initial Flyway production deployments on projects with an existing DB. 
# Be careful when enabling this as it removes the safety net that ensures 
# Flyway does not migrate the wrong database in case of a configuration mistake! (default: false) 
# flyway.baselineOnMigrate= true

Как только я установил для  baselineOnMigrate свойства значение True и запустил еще одну сборку конвейера, я заметил создание schema_version в БД с записью ниже:

Тем не менее, новые изменения схемы не были сделаны Flyway, и я не видел изменений в базе данных.

Здесь следует отметить, что поскольку мы выполнили базовую линию, Flyway установил ее в качестве начальной версии в таблице schema_history. Таким образом, если у вас есть префикс «V1__» для вашего файла SQL, он не будет работать. Чтобы миграция Flyway работала, вам нужно переименовать файл в «V2__».

Как только я внес это изменение и нажал на сборку Jenkins, я смог увидеть скрипт, выполненный Flyway, и запись, сделанную в таблице schema_history.

Сборка Jenkins прошла успешно, и изменения были развернуты во всех средах:

Надеюсь, этот блог был вам полезен. Если это не решит вашу проблему, пожалуйста, не стесняйтесь комментировать ниже, и я был бы рад помочь.