LiquiBase

В этой статье мы рассмотрим работу LiquiBase, с открытым исходным кодом для управления версиями и изменениями схемы базы данных. Это поможет Вам организовать дополнительные изменения в базе данных с различными наборами изменений и применить их для базы данных.

LiquiBase не единственное средство миграции база данных. Есть много решений, такие как Doctrine 2 migrations, Rails AR migrations, DBDeploy, и так далее. Первые два варианта отличные решения, но это платформы. DBDeploy является относительно простым, но он не такой насыщенный, как функции LiquiBase. LiquiBase решает многие проблемы, которые не делают инструменты миграции базы данных, такие как поддержка несколькими разработчиками различных систем управления базами данных.

Кроме того, серьезным недостатком в большинство инструментов является то, что они не знают что изменить. Вместо того чтобы сосредоточиться на изменении, они то и дело сравнивают два снимка схемы базы данных для создания сценария миграции. Так, например, переименование столбцов рассматривается как операциюя drop+add, которая может привести к потере данных. LiquiBase это изменение понимает.

Давайте посмотрим, как использовать LiquiBase в наших проектах.

Как работает LiquiBase

Если вы используете Mac с brew, установка LiquiBase простая. Просто запустите установку LiquiBase brew и всё готово для применения. То же самое и в случае с Ubuntu, sudo apt-get install liquibase сделает это за вас. Двоичный LiquiBase является кросс-платформенным Java — приложением, которое означает, что вы можете скачать JAR и использовать его на Windows, Mac или Linux. LiquiBase нужно сохранить его в папке проекта, и можно каждый проект использовать без дополнительных установок.

При использовании LiquiBase, храните изменения базы данных в формате XML, известный как файл изменений. Изменения могут быть сохранены в один файл или сразу несколько файлов, которые будут включены в мастер-файле изменений. Рекомендуется второй вариант, поскольку он обеспечивает большую гибкость при организации изменений.

В файле изменений, вы организуете изменения для различных изменений. Изменение может содержать одно или несколько изменений, которые необходимо применить к вашей базе данных. Каждое изменение может быть однозначно идентифицирован с помощью идентификаторов и атрибуты автора вместе с классом путь к файлу изменений. LiquiBase создаёт таблицу (databasechangelog) в базу данных для отслеживания успешного применения изменения. Liquibase проходит через каждое установленное изменение один за другим, и проверяет, применяются ли они, путем сравнения контрольной суммы в таблице databasechangelog. Он будет применять изменения, если оно еще не запущен или если он имеет для них метку runAlways.

к меню ↑

Приступая к работе

Для демонстрационных целей, создана база данных с именем приложения на локальном сервере MySQL, а также файл изменений XML. Вы можете сохранить его в папке проекта или в другом месте, но измененные файлы должны быть под контролем версий.

Вот первая версия нашего файла изменений, без изменений.

<?xml version="1.0" encoding="UTF-8"?>
  <!—db.changelog.xml—>
  <databaseChangeLog
  xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-2.0.xsd">
  </databaseChangeLog>

В командной строке перейдите в папку, где вы сохранили файл изменений и выполните следующую команду:

liquibase --driver=com.mysql.jdbc.Driver \
     --classpath=../lib/mysql-connector-java-5.1.21-bin.jar \
     --changeLogFile=db.changelog.xml \
     --url="jdbc:mysql://localhost/application" \
     --username=dbuser \
     --password=secret \
     update

Если LiquiBase может подключиться к базе данных с использованием данного имени пользователя и пароля, он должен создать две таблицы в базе данных приложения, DATABASECHANGELOG и DATABASECHANGELOGLOCK, и показать следующие результаты:

INFO 8/2/12 10:19 AM:liquibase: Successfully acquired change log lock
INFO 8/2/12 10:19 AM:liquibase: Creating database history table with name: `DATABASECHANGELOG`
INFO 8/2/12 10:19 AM:liquibase: Reading from `DATABASECHANGELOG`
INFO 8/2/12 10:19 AM:liquibase: Reading from `DATABASECHANGELOG`
INFO 8/2/12 10:19 AM:liquibase: Successfully released change log lock
Liquibase Update Successful

В приведенной выше команде, все параметры, кроме classpath не требуют, драйвер определяет имя класса драйвера базы данных, которые мы хотим использования changeLogFile название нашей базы данных changelog. url указывает JDBC database connection string, которая включает в себя тип сервера, имя хоста и имя базы данных classpath где вы храните классы, например, базы данных разъем, используемый Liquibase.

Вместо указания параметров командной строки при каждом запуске LiquiBase, вы можете сохранить их в свойствах Java файл liquibase.properties в том же каталоге. После этого можно запустить только LiquiBase <command> свойства файла будет выглядеть следующим образом:

#liquibase.properties
driver: com.mysql.jdbc.Driver
classpath: ../lib/mysql-connector-java-5.1.21-bin.jar
url: jdbc:mysql://localhost/application
changeLogFile: db.changelog.xml
username: dbuser
password: secret

Теперь давайте создадим таблицу пользователей с ID, столбцы с именем и адресом электронной почты, добавив изменений в db.changelog.xml. Вот обновленный XML:

<?xml version="1.0" encoding="UTF-8"?>
  <!—db.changelog.xml—>
<databaseChangeLog
  xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-2.0.xsd">
    <changeSet id="1" author ="shameer">
      <createTable tableName="user">
        <column name="id" type="int">
          <constraints primaryKey="true" nullable="false" />
        </column>
        <column name="name" type="varchar(50)">
          <constraints nullable="false" />
        </column>
        <column name="email" type="varchar(128)">
          <constraints unique="true" nullable="false" />
        </column>
      </createTable>
    </changeSet>
</databaseChangeLog>

createTable принимает имя таблицы в tableName атрибутов и column в отдельные теги. Вы укажете column в таблице со column с тегом его имя и тип данных, как это требуется, attributes. column поддерживает ряд других полезных свойств, которые, возможно, не имеет смысла во всех случаях. Например, вы можете установить, column auto increment с помощью autoIncrement=»true»

Любой column ограничения задаются с тегом constraints. В нашем пример id column первичного ключа, и не нулевого ограничения, а также email column имеет ограничение уникальности.

Запустите LiquiBase и посмотрите на результат:

liquibase update
INFO 8/4/12 7:16 AM:liquibase: Successfully acquired change log lock
INFO 8/4/12 7:16 AM:liquibase: Creating database history table with name: `DATABASECHANGELOG`
INFO 8/4/12 7:16 AM:liquibase: Reading from `DATABASECHANGELOG`
INFO 8/4/12 7:16 AM:liquibase: Reading from `DATABASECHANGELOG`
INFO 8/4/12 7:16 AM:liquibase: ChangeSet db.changelog.xml::1::shameer ran successfully in 74ms
INFO 8/4/12 7:16 AM:liquibase: Successfully released change log lock
Liquibase Update Successful

Если вы посмотрите на базу данных, вы увидите пользователей в таблице со следующей структурой:

*************** 1. row ***************
  Field: id
   Type: int(11)
   Null: NO
    Key: PRI
Default: NULL
  Extra: 
*************** 2. row ***************
  Field: name
   Type: varchar(50)
   Null: NO
    Key: 
Default: NULL
  Extra: 
*************** 3. row ***************
  Field: email
   Type: varchar(128)
   Null: NO
    Key: UNI
Default: NULL
  Extra:

Вы заметили, что мы не имеем auto increment в таблице? Мы можем добавить второй набор изменений, чтобы изменить таблицу и оформить следующие изменения:

  • Изменение id column на auto_increment
  • Переименовать имя column в fullname (полное название)
  • Добавить новый column age
<changeSet id="2" author="shameer">
    <addAutoIncrement tableName="user" columnName="id" columnDataType="int" />
    <renameColumn tableName="user" oldColumnName="name" newColumnName="fullname" columnDataType="varchar(100)"/>
    <addColumn tableName="user">
      <column name="age" type="SMALLINT"/>
    </addColumn>
  </changeSet>

Теги addAutoIncrement сделают id column и автоматически увеличат. renameColumn будет переименовать column, приняв имя column можно изменить в атрибут oldColumnName и новое имя в newColumnName.

Давайте запустим LiquiBase, а затем посмотрим на пользователей таблицы. Вы должны увидеть два измененных column и новый age колонки.

к меню ↑

Создание изменений файла

Что делать, если вы уже начали ваш проект без LiquiBase, потом трудно реализовать его, будет иметь дело с изменениями в базе данных без некоторой автоматизации механизма? LiquiBase поставляется с удобной функцией для создания изменений файла с существующими схемами. Используйте следующую команду для создания изменений файла с именем, указанным в liquibase.properties .

LiquiBase generateChangeLog

Созданная изменений будет создавать отчеты за каждую таблицу в базе данных.

При разработке приложения на локальном компьютере, проще вносить изменения непосредственно в MySQL, чем создавать файлы изменений для каждого изменения. Но мы должны иметь эти изменения через несколько разработчиков в команде. К счастью, LiquiBase также обеспечивает возможность сравнить две базы данных и создавать списки изменений.

Вот шаги для создания журнала изменений файла для вновь создаваемых таблиц в базе данных:

  1. Сделайте резервную копию базы данных с помощью mysqldump
  2. Создать временную базу данных
  3. Импорт дампа временной базы данных
  4. Отбросьте все изменения, сделанные в исходной базе данных
  5. Создание изменений с использованием LiquiBase.
liquibase diffChangeLog \
--referenceUrl=jdbc:mysql://localhost/application_temp \
--referenceUsername=dbuser \
--referencePassword=secret

Это позволит добавить новые изменений в db.changelog.xml для создания недостающих таблиц в базе данных.

<changeSet author="shameerc (generated)" id="1344051849388-1">
    <createTable tableName="temp">
      <column autoIncrement="true" name="id" type="INT">
        <constraints nullable="false" primaryKey="true"/>
      </column>
      <column name="name" type="VARCHAR(200)"/>
      <column name="value" type="TEXT"/>
    </createTable>
  </changeSet>

Как только создано, вы должны проверить и убедиться в этом, в локальной базе данных, прежде чем применить его в управление версиями. Также будьте осторожны при создании изменений файлов, LiquiBase рассмотрит переименование колон в виде drop+add column, который приведет к потере данных.

к меню ↑

Откат изменений

До сих пор мы только смотрели на внесение изменений в нашей базе данных. Но что, если нам нужно отменить изменения, после того как они были применены к базе данных? Мы можем легко откатить изменения, внесенные через LiquiBase использованием команды отката.

Большинство теги рефакторинг, такие как createTable и renameColumn будет автоматически генерировать rollback. Если это не удовлетворяет вашим потребностям, вы можете добавлять пользовательские rollback для набора изменений. Вы можете сделать откат к определенному количеству набору предыдущих изменений, до определенной даты, или конкретного тега, который вы создали ранее!

liquibase rollbackCount 1

LiquiBase позволяет добавлять контрольно-пропускные пункты в нашу базу данных с помощью меток текущего состояния. Это помогает нам легко откатить к определенному состоянию, просто вызывая его тег.

liquibase tag checkpoint_1

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

liquibase rollback checkpoint_1

Вы можете проверить, SQL применяется для отката изменений. Для достижения этой цели, заменить откат с rollbackSql и rollbackCount с rollbackCountSql. LiquiBase выведет результат на стандартный вывод, который можно перенаправить в файл и сохранить для последующего выполнения.

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

<changeSet id="6" author="shameer">
    <modifyDataType columnName="value" newDataType="TEXT" tableName="temp"/>
    <rollback>
      <dropTable tableName="temp"/>
    </rollback>
  </changeSet>

Вы можете проверить это путем создания отката в SQL после применения изменений.

liquibase rollbackCountSql 1

-- Lock Database
-- Rolling Back ChangeSet: db.changelog.xml::6::shameer::(Checksum: 3:29343b94088e34367e51a6633f572b81)
DROP TABLE `temp`;

DELETE FROM `DATABASECHANGELOG`  WHERE ID='6' AND AUTHOR='shameer' AND FILENAME='db.changelog.xml';

-- Release Database Lock
Liquibase Rollback Successful
к меню ↑

Состояние применённых изменений

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

<changesSet id="8" author="shameer">
 <preConditions onFail="CONTINUE">
  <sqlCheck expectedResult="0">select count(*) from user</sqlCheck>
 </preConditions>
 <dropTable tableName="user"/>
</changesSet>

В этом случае LiquiBase сначала проверит, таблица содержит записи пользователя, и если да, то будет продолжать без выполнения изменений. Если Condtion важно, вы можете остановить выполнение, установив onFail = «HALT» вместо CONTINUE.

Есть много других удобных функций, таких как проверка, какие базы данных использует система, имя пользователя текущего пользователя и т.д. Вы можете узнать больше на сайте liquibase.

к меню ↑

Заключение

В этой статье мы говорили о LiquiBase, рефакторинг баз данных и инструменты управления изменениями. Наиболее важное использование LiquiBase является синхронизация изменений баз данных с несколькими разработчиками в команде, когда вы внести некоторые изменения в локальной базе данных, другие разработчики могут вытянуть эти изменения и применять в своих машинах. Изменения будут в каждом версий изменений, и вы можете легко откатить к предыдущему состоянию, если что-то пойдет не так. Кроме того, вы можете использовать LiquiBase для миграции баз данных и развертывания. В этой статье не все возможности LiquiBase, LiquiBase имеет очень хорошее руководство которое вам обязательно надо почитать.

htmlhook.ru | Скрипты для веб-приложений