Версионирование структуры БД при помощи Liquibase |
||
|
МЕНЮ Главная страница Поиск Регистрация на сайте Помощь проекту Архив новостей ТЕМЫ Новости ИИ Голосовой помощник Разработка ИИГородские сумасшедшие ИИ в медицине ИИ проекты Искусственные нейросети Искусственный интеллект Слежка за людьми Угроза ИИ ИИ теория Внедрение ИИКомпьютерные науки Машинное обуч. (Ошибки) Машинное обучение Машинный перевод Нейронные сети начинающим Психология ИИ Реализация ИИ Реализация нейросетей Создание беспилотных авто Трезво про ИИ Философия ИИ Big data Работа разума и сознаниеМодель мозгаРобототехника, БПЛАТрансгуманизмОбработка текстаТеория эволюцииДополненная реальностьЖелезоКиберугрозыНаучный мирИТ индустрияРазработка ПОТеория информацииМатематикаЦифровая экономика
Генетические алгоритмы Капсульные нейросети Основы нейронных сетей Распознавание лиц Распознавание образов Распознавание речи Творчество ИИ Техническое зрение Чат-боты Авторизация |
2021-03-28 13:58 Большая часть приложений, которые мне встречались, хранят данные в SQL базе данных. Если у вас корпоративное приложение, то скорее всего имеется несколько стендов: стенд разработки, пре-прод и прод. А над приложением трудится команда разработчиков. Такие приложения сталкиваются с проблемой синхронизации схемы БД между контурами и самими разработчиками. Надо как-то передать изменения, которые вы внесли всем остальным и при этом не получить конфликты. Эти проблемы решает система управления миграциями Liquibase. Это своего рода система контроля версий вашей базы данных. Liquibase - независимая от базы данных библиотека для отслеживания, управления и применения изменений схемы базы данных. Изменения для БД записываются в формате понятном Liquibase, а уже он в свою очередь выполняет запросы к базе данных. Таким образом реализуется независимость от конкретной БД. Liquibase поддерживает 10 типов баз данных, включая DB2, Apache Derby, MySQL, PostgreSQL, Oracle, Microsoft® SQL Server, Sybase и HSQL. Список всех поддерживаемых БД можно посмотреть на сайте. Существует другие системы управления миграциями: Doctrine 2 migrations, Rails AR migrations, DBDeploy и т.д. Но некоторые из них платформо-зависимые, некоторые не обладают таким широким функционалом. Также серьезный недостаток многих систем — невозможность применения некоторых изменений без потери данных, например, переименование столбца произойдет как две операции: drop + add, что приведет к потере данных. Как работает Liquibase Liquibase — кросс платформенное Java приложение, это значит, что вы можете скачать JAR файл и использовать его на Windows, Mac или Linux. Для примера мы будем рассматривать работу со spring-boot приложением и PostgresSQL базой данных. Но вы должны знать, что liquibase можно использовать и отдельно в виде .jar файла. Вот так: java -jar liquibase.jar --driver=com.mysql.jdbc.Driver--classpath=lib/mysql-connector-java-5.1.21-bin.jar --changeLogFile=/path/to/changelog.yaml --url="jdbc:mysql://localhost/application" --username=dbuser --password=secret update Changelog Изменения структуры базы данных записываются в файлы, которые называются changelog. Поддерживаемые форматы: XML, YAML, JSON или SQL. Файлы изменений могут быть произвольно включены друг в друга для лучшего управления. Подробнее об этом ниже. Я являюсь ярым противником XML конфигураций, но в данном случае это самый удобный формат для записи миграций. ChangeSet ChangeSet – это аналог коммита в системах контроля версий, таких как Git. ChangeSet может содержать одно или несколько изменений базы данных. Хорошей практикой считается одна команда для одного ChangeSet. Каждый changeSet имеет составной идентификатор При первом запуске Liquibase создает две технические таблицы:
Блокировка Если несколько экземпляров Liquibase будут выполняться одновременно с одной и той же базой данных, вы получите конфликты. Это может произойти, если несколько разработчиков используют один и тот же экземпляр базы данных или если в кластере несколько серверов, которые автоматически запускают Liquibase при запуске. Для защиты от таких ситуаций Liquibase создает таблицу Экстренно остановив выполнение программы в самом начале, может сложиться ситуация при котором Liquibase успеет поставить флаг, но не поменяет его на ![]() Чтобы исправить эту проблему, в таблице ![]() Контрольная сумма Далее Liquibase читает главный changelog, проверяя какие изменения уже были приняты, а какие надо выполнить. После выполнения changeSet в таблицу При следующем запуске Liquibase будет сверять вновь рассчитанные хэш суммы, со значениями в его таблице. Если вы изменили уже выполненный changeSet, то хэш сумма будет отличаться, и приложение упадет с ошибкой при старте. ![]() После выполнения changeset нельзя изменить Начало работы И так у нас уже есть spring-boot приложение, в которое мы хотим добавить Liquibase. Репозиторий с примерами из статьи на GitHub: Настройка для spring-boot Чтобы добавить поддержку Liquibase, нужно указать следующие зависимости в maven: <dependency> <groupId>org.liquibase</groupId> <artifactId>liquibase-core</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-jpa</artifactId> </dependency> Так же в файл spring: datasource: url: jdbc:postgresql://localhost:5432/liquibase_example username: postgres driver-class-name: org.postgresql.Driver password: password Если вы используете Hibernate, то не забудьте отключить создание схемы БД. Теперь нам необходимо создать главный changelog. По умолчанию в spring-boot Liquibase ищет его в папке Создаем файл spring: # .. .. .. .. .. liquibase: change-log: classpath:db/changelog/db.changelog-master.xml Вставляем начальное содержимое в файл: <databaseChangeLog xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.liquibase.org/xml/ns/dbchangelog" xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-3.1.xsd"> // сюда пишутся changeSets </databaseChangeLog> Чтобы быстро получить результат, мы создадим changeSet прямо в этом файле, а потом я расскажу почему так делать не стоит. Создание таблицы Создадим таблицу Person. <changeSet id="create-table-person" author="uPagge"> <createTable tableName="person"> <column name="id" type="int" autoIncrement="true"> <constraints nullable="false" primaryKey="true"/> </column> <column name="name" type="varchar(64)"/> <column name="telegram_id" type="int"> <constraints unique="true"/> </column> </createTable> </changeSet> Тег Для колонок обязательно необходимо указать тип. Тип указывается в формате Liquibase, после чего он приводится для конкретной реализации БД. Отдельного внимания заслуживает колонка id. Для нее мы задали автоинкремент, а так же в
После запуска spring-boot приложения у нас будет создано 3 таблицы, одна из которых и будет Добавление колонки в таблицу А теперь попробуем добавить новую колонку в таблицу в этом changeSet. Изменим его: <changeSet id="create-table-person" author="uPagge"> <createTable tableName="person"> <column name="id" type="int" autoIncrement="true"> <constraints nullable="false" primaryKey="true"/> </column> <column name="name" type="varchar(64)"/> <column name="telegram_id" type="int"> <constraints unique="true"/> </column> <column name="address" type="varchar(300)"/> </createTable> </changeSet> Снова запустив приложение мы получим ошибку. Если changeSet уже выполнился, и запись об этом есть в В этом случае у вас три пути:
Вернем changeSet в его предыдущее состояние и создадим новый: <changeSet id="create-table-person" author="uPagge"> <createTable tableName="person"> <column name="id" type="int" autoIncrement="true"> <constraints nullable="false" primaryKey="true"/> </column> <column name="name" type="varchar(64)"/> <column name="telegram_id" type="int"> <constraints unique="true"/> </column> </createTable> </changeSet> <changeSet id="add-new-column-address" author="uPagge"> <addColumn tableName="person"> <column name="address" type="varchar(300)"/> </addColumn> </changeSet> Запускаем приложение. На этот раз успешно, новая колонка добавилась. ![]() Связь с другой таблицей Связь между таблицами довольно частое явление. Добавим новую таблицу <changeSet id="create-table-book" author="uPagge"> <createTable tableName="book"> <column name="id" type="int" autoIncrement="true"> <constraints nullable="false" primaryKey="true"/> </column> <column name="name" type="varchar(64)"/> <column name="author_id" type="int"> <constraints foreignKeyName="book_author_id_person_id" references="person(id)"/> </column> </createTable> </changeSet> Теперь атрибут При этом обязательно нужно указать уникальный Также мы можем указать тип каскадной операции: <constraints foreignKeyName="book_author_id_person_id" references="person(id)" deleteCascade="true"/> Теперь, если автор книги будет удален, то книга тоже будет удалена. Если вам необходима операция каскадного обновления, то вам нужен второй способ связи с таблицей: <changeSet id="create-table-book" author="uPagge"> <createTable tableName="book"> <column name="id" type="int" autoIncrement="true"> <constraints nullable="false" primaryKey="true"/> </column> <column name="name" type="varchar(64)"/> <column name="author_id" type="int"/> </createTable> <addForeignKeyConstraint baseTableName="book" baseColumnNames="author_id" constraintName="book_author_id_person_id" referencedTableName="person" referencedColumnNames="id" onUpdate="CASCADE"/> </changeSet> Создание представления Несмотря на то, что к этому моменту вы уже полюбили создание изменений с помощью XML, для создания представления придется использовать SQL: <changeSet id="create-view-book-author" author="uPagge"> <createView viewName="author_and_book"> SELECT p.id as person_id, p.name as person_name, b.id as book_id, b.name as book_name FROM person p LEFT JOIN book b on p.id = b.author_id </createView> </changeSet> Советы от бывалых Познакомился я с Liquibase на своей стажировке в 2017. С тех пор я использую Liquibase на своих домашних проектах, и продвигаю его использование на рабочих. Мне уже проще написать changeSet, чем SQL. Поэтому далее будет небольшой список рекомендаций, которые облегчат вам жизнь. Организация ChangeSet Добавляя все changeSet в один changelog у вас могло закрасться сомнение: а все ли мы правильно делаем. Схема БД может довольно динамично меняться, особенно в начале создания приложения, поэтому мы ожидаем множество changeSet. Можно создавать множество ChangeLog и включать их друг в друга. Далее я расскажу о своем подходе к организации changelog. Я придерживаюсь следующего подхода:
Во время выпуска релиза у вас могут оказаться запросы на слияния, которые затрагивают добавления новых changeSet. В этих ПР необходимо создать новую папку для новых changeLogs с номером нового релиза и перенести туда changeLogs для этих ПРов. Правила именования Правило именования файлов позволяет без просмотра кумулятивных чейнджлогов файлов понять, что за чем следовало, и не допустит случайного повторения Вы можете придумать свои правила, но вот что предлагаю я:
Не изменяйте данные Работа с данными в БД не входит в число ключевых фич Liquibase и ограничивается лишь простейшими операциями вставки и удаления или изменения. Исходя из своего опыта крайне не рекомендую изменять данные с помощью Liquibase.
Используйте XML Иногда хочется «облегчить» жизнь и отказаться от XML, начав использовать более краткий DSL: groovy, yaml, json. Все это очень хорошо до тех пор, пока вам не захочется иметь:
Используйте remark Разработчики стараются давать понятные имена для переменных, но дополнительное описание не будет лишним. Параметр <changeSet id="2021-02-22-create-person" author="uPagge"> <createTable tableName="person" remarks="Пользователи системы"> <column name="id" type="int" autoIncrement="true" remarks="Идентификатор"> <constraints nullable="false" primaryKey="true"/> </column> <column name="name" type="varchar(64)" remarks="Имя пользователя"> <constraints nullable="false"/> </column> <column name="telegram" type="int" remarks="Идентификатор в телеграмм"> <constraints unique="true"/> </column> </createTable> </changeSet> Итого Эта же статья в момем блоге: Версионирование структуры БД при помощи Liquibase. В этой статье мы обсудили логику работы Liquibase, а так же простое внедрение его в ваше приложение. Этого уже достаточно, чтобы начать пользоваться Liquibase. В следующей статье я расскажу, как откатывать изменения. Используете liquibase на проектах? Java ffentliche Umfrage 2 Stimmen Источник: habr.com Комментарии: |
|