Содержание


Автоматизация для программистов

Автоматизированная миграция баз данных

Использование LiquiBase для внесений изменений в базы данных

Comments

Серия контента:

Этот контент является частью # из серии # статей: Автоматизация для программистов

Следите за выходом новых статей этой серии.

Этот контент является частью серии:Автоматизация для программистов

Следите за выходом новых статей этой серии.

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

  • ручное внесение изменений в БД;
  • разные версии БД у разных участников команды разработчиков;
  • непоследовательные подходы к внесению изменений (в базу данных или данные);
  • неэффективные механизмы ручного управления изменениями при переходах между версиями баз данных.

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

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

Рисунок 1. Ручное внесение изменений в таблицу базы данных
Рисунок 1. Ручное внесение изменений в таблицу базы данных

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

  • использование инструмента LiquiBase для миграции между различными версиями одной и той же базы данных;
  • автоматическое выполнение миграции базы данных;
  • способы последовательного внесения изменений в базе данных;
  • выполнение рефакторинга базы данных при помощи LiquiBase.

На рисунке 2 сервер постоянной интеграции и сборки (build/continuous Integration server) опрашивает на предмет изменений систему контроля версий (например, Subversion). Когда сервер обнаруживает изменение в репозитории, он запускает автоматический сценарий сборки, который использует LiquiBase для обновления базы данных

Рисунок 2. Автоматизация миграции базы данных
Рисунок 2. Автоматизация миграции базы данных
Рисунок 2. Автоматизация миграции базы данных

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

Управление изменениями в базе данных с помощью LiquiBase

Продукт LiquiBase, развиваемый с 2006 года, - это бесплатный инструмент с открытым исходным кодом, предназначенный для миграции с одной версии базы данных на другую (см. раздел Ресурсы). Кроме LiquiBase, имеются и другие утилиты с открытым исходным кодом, предназначенные для миграции баз данных, например, openDBcopy и dbdeploy. LiquiBase поддерживает 10 типов баз данных, включая DB2, Apache Derby, MySQL, PostgreSQL, Oracle, Microsoft® SQL Server, Sybase и HSQL.

Чтобы установить LiquiBase, необходимо загрузить заархивированный файл ядра LiquiBase, распаковать его и поместить файл liquibase-version.jar в общесистемный путь поиска программ (переменная PATH).

Чтобы начать работать с LiquiBase, нужно выполнить четыре шага:

  1. Создать файл с журналом изменений в базе данных (change log).
  2. Определить набор изменений (change set - XML-элемент) внутри этого файла.
  3. Применить набор изменений к базе данных через командную строку или сценарий сборки.
  4. Проверить изменения в базе данных.

Создание файла change log и XML-элемента change set

Первым шагом для работы с LiquiBase, как демонстрируется в листинге 1, является создание XML-файла, известного как журнал изменений в базе данных (database change log):

Листинг 1. Определение набора изменений в XML-файле LiquiBase
<?xml version="1.0" encoding="UTF-8"?>

<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog/1.7"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog/1.7
         http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-1.7.xsd">
  <changeSet id="2" author="paul">
    <createTable tableName="brewer">
      <column name="id" type="int">
        <constraints primaryKey="true" nullable="false"/>
      </column>
      <column name="name" type="varchar(255)">
        <constraints nullable="false"/>
      </column>
      <column name="active" type="boolean" defaultValue="1"/>
    </createTable>
  </changeSet>
</databaseChangeLog>

Как можно видеть, log-файл database change содержит ссылку на XML-схему (файл dbchangelog-1.7.xsd включен в установочный пакет LiquiBase). В узле change log создается узел <changeSet>. Как показано в схеме LiquiBase, внутри <changeSet> в структурированном формате определяются изменения в базе данных.

Выполнение LiquiBase из командной строки

После определения блока change set можно запустить LiquiBase из командной строки способом, показанным в листинге 2:

Листинг 2. Запуск LiquiBase из командной строки
liquibase --driver=org.apache.derby.jdbc.EmbeddedDriver \
--classpath=derby.jar \
--changeLogFile=database.changelog.xml \
--url=jdbc:derby:brewery;create=true \ 
--username= --password= \
update

В этом примере при запуске LiquiBase ему передаются следующие параметры:

  • драйвер базы данных;
  • значение переменной classpath для определения местоположения JAR-файла драйвера базы данных;
  • название change log-файла, который был создан в листинге 1 - database.changelog.xml;
  • URL-адрес базы данных;
  • имя пользователя и пароль.

В заключение в листинге 2 вызывается команда update, которая указывает LiquiBase внести изменения в базу данных.

Запуск LiquiBase в ходе автоматизированной сборки

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

Листинг 3. Ant-сценарий для выполнения задачи Ant updateDatabase
<target name="update-database">
  <taskdef name="updateDatabase" classname="liquibase.ant.DatabaseUpdateTask" 
    classpathref="project.class.path" />
  <updateDatabase changeLogFile="database.changelog.xml"
    driver="org.apache.derby.jdbc.EmbeddedDriver"
    url="jdbc:derby:brewery"
    username=""
    password=""
    dropFirst="true"
    classpathref="project.class.path"/>
</target>

В листинге 3 создается элемент с названием update-database. В нем определяется Ant-задача с именем updateDatabase, относящаяся к LiquiBase. В нее передаются необходимые значения, включая changeLogFile (определяет файл с журналом изменений, описанный в листинге 1) и информацию для подключения к базе данных. В переменной classpath, задаваемой атрибутом classpathref, должен содержаться путь к файлу liquibase-version.jar.

До и после

Рисунок 3 показывает состояние базы данных до того, как в нее был внесен набор изменений из листинга 1:

Рисунок 3. Состояние базы данных до выполнения набора изменений LiquiBase
Рисунок 3. Состояние базы данных до выполнения набора изменений LiquiBase

Рисунок 4 показывает результаты выполнения набора изменений из элемента change set для базы данных из командной строки (как показано в листинге 2) или из Ant (как показано в листинге 3):

Рисунок 4. Изменения, внесенные в базу данных после выполнения набора изменений LiquiBase
Рисунок 4. Изменения, внесенные в базу данных после выполнения набора изменений LiquiBase
Рисунок 4. Изменения, внесенные в базу данных после выполнения набора изменений LiquiBase

Ряд аспектов на рисунке 4 заслуживает отдельного рассмотрения. Кроме новых таблиц, которые были созданы на основе описания в XML-элементе change set (см. листинг 1), LiquiBase создал две специальные таблицы. Первая LiquiBase-специфичная таблица, называемая databasechangelog, хранит историю всех изменений, сделанных в базе данных - она позволяет отслеживать, кто внес изменения в базу данных и зачем. Вторая специфичная для LiquiBase таблица, databasechangelock, определяет пользователя, который заблокировал базу данных для внесения в нее изменений.

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

Интеграция изменений в БД

В течение последних лет команды разработчиков привносили в управление изменениями в базах данных принципы, подобные тем, которые используются при работе с исходным кодом. Поэтому вполне закономерно создание сценариев изменения для БД, загрузка этих сценариев в репозитории исходного кода и интеграция этих изменений в процесс постоянной сборки (Continuous-Integration process). В таблице 1 предоставлен обзор ключевых возможностей, которые следует использовать командам разработчиков при автоматизации процесса внесения изменений в БД:

Таблица 1. Подходы к интеграции баз данных
МетодикаОписание
Создание DDL- и DML-сценариевВсе сценарии изменения БД должны иметь возможность запуска из командной строки.
Использование системы контроля версий для управления изменениями в данныхДля управления изменениями в базе данных используется репозиторий системы контроля версий.
Локальная база данных - "песочница"Каждый разработчик вносит изменения в собственную локальную базу данных.
Автоматизированная интеграция в базу данныхПроцесс внесения изменений в базу данных стать частью процесса автоматической сборки.

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

Внесение изменений в уже существующую базу данных

Когда в приложение добавляются новые возможности, часто возникает необходимость вносить структурные изменения в базу данных или изменять ограничения таблиц. LiquiBase поддерживает более 30 команд для рефакторинга баз данных (см. раздел Ресурсы). Этот раздел затрагивает четыре из этих команд: добавление столбца, удаление столбца, создание таблицы и управление данными.

Добавление столбца

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

Листинг 4. Использование команды Add Column для рефакторинга базы данных через набор изменений LiquiBase
<changeSet id="4" author="joe">
  <addColumn tableName="distributor">
    <column name="phonenumber" type="varchar(255)"/>
  </addColumn> 
</changeSet>

Новый столбец phonenumber имеет тип данных varchar.

Удаление столбца

Теперь предположим, что через несколько версий было решено удалить столбец phonenumber, добавленный в листинге 4. Это легко сделать при помощи XML-команды dropColumn, как показано в листинге 5:

Листинг 5. Удаление столбца из базы данных
<dropColumn tableName="distributor" columnName="phonenumber"/>

Создание таблицы

Добавление новой таблицы к базе данных - еще одна задача, часто возникающая при рефакторинге базы данных. В листинге 6 создается новая таблица с именем distributor; при этом определяются столбцы, ограничения и значения по умолчанию для новой таблицы:

Листинг 6. Создание новой таблицы в LiquiBase
<changeSet id="3" author="betsey">
  <createTable tableName="distributor">
    <column name="id" type="int">
      <constraints primaryKey="true" nullable="false"/>
    </column>
    <column name="name" type="varchar(255)">
      <constraints nullable="false"/>
    </column>
    <column name="address" type="varchar(255)">
      <constraints nullable="true"/>
    </column>
    <column name="active" type="boolean" defaultValue="1"/>
  </createTable>
</changeSet>

В данном примере команда рефакторинга createTable является вложенным узлом XML-элемента changeSet (команда createTable также использовалась в примере из листинга 1).

Управление данными

После рефакторинга структуры БД (например, с помощью команд Add Column и Create Table) часто бывает нужно вставить данные в измененные таблицы. Более того, может потребоваться изменение уже существующих данных в таблицах преобразования и других типах таблиц. В листинге 7 приведен пример того, как вставить данные через XML-элемент changeSet LiquiBase:

Листинг 7. Вставка данных через XML-элемент changeSet LiquiBase
<changeSet id="3" author="betsey">
  <code type="section" width="100%">
  <insert tableName="distributor">
    <column name="id" valueNumeric="3"/>
    <column name="name" value="Manassas Beer Company"/>
  </insert>
  <insert tableName="distributor">
    <column name="id" valueNumeric="4"/>
    <column name="name" value="Harrisonburg Beer Distributors"/>
  </insert>
</changeSet>

Возможно, у вас уже есть готовые SQL-сценарии для управления данными, или возможности LiquiBase XML кажутся несколько ограниченными. Кроме того, SQL-сценарии иногда удобнее для внесения массовых изменений в БД. LiquiBase может работать с SQL-файлами. В листинге 8 показан фрагмент кода, в котором в XML-элементе changeSet вызывается файл insert-distributor-data.sql, который вставляет данные в таблицу distributor:

Листинг 8. Запуск произвольного SQL-файла из XML-элемента changeSet LiquiBase
<changeSet id="6" author="joe">
  <sqlFile path="insert-distributor-data.sql"/>
</changeSet>

LiquiBase поддерживает многие другие команды рефакторинга базы данных, включая добавление таблицы преобразования и слияние столбцов. Они определяются так же, как показано в листингах с 4 по 8-й.

Постоянная синхронизация данных

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

  • показать, как использовать LiquiBase для создания сценариев миграции баз данных и как сделать эти изменения частью автоматизированного процесса сборки;
  • описать принципы и практические подходы к интеграции баз данных, обеспечивающие согласованность процесса;
  • показать, как использовать команды рефакторинга типа addColumn и createTable для изменения структуры таблиц и обновления данных средствами LiquiBase

Таблица 2 подытоживает некоторые возможностей, предоставляемых LiquiBase:

Таблица 2. Сводная информация по возможностям LiquiBase
ВозможностьОписание
Поддержка различных баз данныхПоддержка DB2, Apache Derby, MySQL, PostgreSQL, Oracle, Microsoft SQL Server, Sybase, HSQL и других производителей.
Просмотр истории изменений, сделанных в БДИспользуя таблицу databasechangelog,можно просмотреть изменения, внесенные в базу данных.
Создание журналов различия баз данныхУзнать об изменениях, которые были внесены в БД, минуя наборы изменений LiquiBase.
Возможность выполнения произвольных SQL-сценариевИспользование LiquiBase для вызова написанных ранее SQL-сценариев.
Утилиты для отката внесенных измененийПоддержка возможности отката любых внесенных в БД изменений.

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


Ресурсы для скачивания


Похожие темы

  • Automation for the people: Hands-free database migration: оригинал статьи (EN).
  • LiquiBase: ресурсы по LiquiBase на Интернет-сайте проекта, включая полный список команд рефакторинга, которые поддерживает LiquiBase.(EN)
  • Incremental Migration: (EN) (Мартин Фаулер, martinfowler.com, июль 2008 г.): в статье утверждается, что поскольку миграция данных является сложным процессом, ее следует выполнять чаще.
  • Refactoring Databases: Evolutionary Database Design: (Скотт Эмблер и Прамод Садаладж, Addison-Wesley Professional, 2006 г.): книга о том, как развивать и управлять схемами базы данных параллельно с управлением исходным кодом.(EN)
  • Continuous Integration: Improving Software Quality and Reducing Risk (Поль Дюваль, Стив Матиас и Эндрю Гловер, Addison-Wesley Signature Series, 2007 г.): примеры в главе 5, "Continuous Database Integration", ("Постоянная интеграция базы данных") демонстрируют, как встроить интеграцию базы данных в автоматизированный процесс сборки.(EN)
  • Recipes for Continuous Database Integration: Evolutionary Database Development: (Прамод Садаладж, Addison-Wesley Professional, 2007 г.): книга о том, как реализовать процесс постоянной интеграции для базы данных.(EN)
  • Evolutionary Database Design (EN) (Фаулер и Садаладж, martinfowler.com, 2003 г.): статья о постоянной интеграции и автоматизированном процессе рефакторинга при разработке баз данных.(EN)
  • Database Integration in your Build scripts (EN) (Поль Дюваль, testearly.com, июль 2006 г.): статья о применении DDL- и DML-сценариев в рамках автоматизированного процесса сборки.
  • LiquiBase: загрузите LiquiBase и автоматизируйте процесс миграции баз данных.(EN)
  • Ant: загрузите Ant и обеспечьте предсказуемость и повторяемость процесса сборки ПО.(EN)
  • developerWorks на Твиттер.(EN)
  • Загрузите ознакомительные версии продуктов IBM и получите доступ к инструментам для разработки и отладки приложений, а также ПО связующего уровня DB2®, Lotus®, Rational®, Tivoli® и WebSphere®.(EN)
  • Усовершенствуйте свой проект с открытым исходным кодом с помощью ознакомительных версий ПО от IBM, которые можно скачать с сайта или заказать на DVD.(EN)

Комментарии

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

static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=40
Zone=Технология Java, Open source
ArticleID=594382
ArticleTitle=Автоматизация для программистов: Автоматизированная миграция баз данных
publish-date=12062010