Статьи

16.08.10

idler

Версионирование схемы MySQL в PHP проектах.

в рубрике web-разработка, Разработки, Технологии, новые продукты , теги: ,

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

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

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

  • Минимум зависимостей — желательно только PHP (без дополнительных расширений) и MySQL.
  • Возможность производить произвольные изменения схемы непосредственно, используя для этого любой доступный клиент (mysql или PHPMyAdmin, например)
  • Полностью автоматизированная генерация миграций.
  • Возможность использовать инструмент в скриптах или в cron.

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

Итак, претендент первый: Doctrine 1.2

Это ORM (Object-relational mapping или Объектно-реляционное отображение), написанный на PHP, но тянет за собой достаточно большую библиотеку классов, и требует установленного PDO. Инструмент этот не попадает под первое же требование, но я решил, что можно использовать и его.

Что же предлагает разработчику Doctrine? Для начала нужно сгенерировать конфигурационный файл схемы — это будет описание схемы БД в YAML-формате. Менять схему придется там же, а значит придется ознакомиться с документацией на формат описания схемы.

Мы меняем конфиг-файл, затем даем задачу сгенерировать миграцию, затем должны перестроить модели (Да-да, все равно придется иметь классы моделей, даже если мы не используем Doctrine в основном проекте), и только потом накатить миграцию на текущую рабочую базу.

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

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

Претендент второй: MySQL Workbench

Это инструмент от Sun(Oracle) с графическим пользовательским интерфейсом. Он позволяет соединиться с базой и построить на ее основе диаграмму таблиц и их связей. В эту диаграмму мы можем вносить любые изменения, при помощи графического интерфейса. Когда изменения внесены мы можем снова соединиться с БД и опубликовать сделанные изменения. Очень удобный инструмент, когда разработка ведется на одной машине и не очень опытным программистом.

Мне же этот инструмент не подошел по причине слишком большого количества ручного труда.

Да и в процессе использования возникали вопросы:

А что если тестовых серверов несколько?

Как наладить обмен ALTER-TABLE-скриптами внутри команды разработчиков?

Еще один вариант:

К этому моменту обмен изменениями БД уже был кое-как налажен. Был написан скрипт ( http://www.antonoff.info/phps/db_migration_tool ) который исполнял только новые *.sql файлы, появляющиеся в определенной папке проекта. Новизну он определял сравнивая дату в имени файла с датой последнего обновления, хранящегося в БД. SQL-скрипты разработчики писали и именовали вручную. Файлы писались уже после того, как изменения внесены в БД на локальной машине разработчика, а потому здесь снова большую роль играл человеческий фактор: забыли написать файл, забыли добавить в файл некоторые жизненно необходимые изменения, наделали синтаксических ошибок и т. п.

От человеческого фактора надо избавляться, но как? Конечно же полностью автоматической генерацией миграций, но возможность подправить что-то вручную обязательно нужно оставить, и при этом нужно сделать так, чтобы это было просто и без чтения дополнительной документации.

С этого момента поиски мои шли только в направлении полностью автоматизированного процесса.

Следующим претендентом стал проект, найденный на Google Code:

Mysql PHP Migrations

http://code.google.com/p/mysql-php-migrations/wiki/Installation

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

Ruby on Rails

Перед тем как начать разработку я решил еще проверить как обстоят дела в Ruby on Rails. Там ситуация оказалась такой же печальной: Нужно запустить генератор, чтобы получить на выходе пустой класс миграции, в который опять же стоит добавить код для миграции вперед и назад. К тому же код на ruby, а его в моей команде никто не знал.

Теперь о моей разработке:

http://www.antonoff.info/development/mysql-migration-with-php-project

http://bitbucket.org/idler/mmp

Вот требования которые были предъявлены к ней на старте:

  • Минимум зависимостей — желательно только PHP (без дополнительных расширений) и MySQL.
  • Возможность производить произвольные изменения схемы непосредственно, используя для этого любой доступный клиент (mysql или PHPMyAdmin например)
  • Полностью автоматизированная генерация миграций.
  • Возможность использовать инструмент в скриптах или в cron.
  • Возможность мигрировать на произвольную версию схемы
  • Возможность произвольно именовать таблицу, хранящую версию схемы ( в Doctrine и в MPM имя этой таблицы жестко прошито в коде)
  • Возможность вывести список доступных миграций с датами
  • Возможность изменять имя каталога в котором хранятся файлы миграций.
  • Читабельность кода, который будет создан при генерации класса миграции
  • Command Line-интерфейс (другого мне и не нужно)
  • Возможность легко добавлять под-команды утилиты (плагины? - Скорее отдельные классы как плагины)

Что мы умеем?

  • Создать начальную миграцию.
  • Накатить начальную миграцию, т. е. инициализировать первую версию БД
  • Создать миграцию, самостоятельно сгенерив весь SQL-код.
  • Показать список миграций, пометив текущую звездочкой.
  • Мигрировать на указанную дату-время.

Дата-время на которые будет произведена миграция указываются в формате, понимаемом PHP-функцией strtotime.

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

При генерации нового миграционного класса MMP создает временную базу, в которую по очереди накатывает все существующие миграции, получая в итоге последнюю версию схему до ваших локальных изменений. Далее MMP сравнивает таблицы и поля внутри таблиц между двумя базами и создает SQL-запросы, которые приведут к тому, что временная база станет такой же как и рабочая. SQL-запросы пишутся в файл-класс миграции. При осуществлении миграции на определенную дату MMP определяет в какую сторону нужно мигрировать (вперед или назад) от текущего состояния, определяет миграции, которые нужно исполнить и их порядок. Далее в прямом или обратном порядке запускает эти миграции с нужным методом (up или down), который в свою очередь исполняет нужные запросы к базе.

Зависимости:

Консольная версия PHP >= 5.3.0

Расширение MySQLi (обычно статически слинковано в PHP)

MySQL >= 5.0 (возможно будет работать и на 4.1)

Как использовать?

Три раза в день, по чайной ложке после еды — до полного просветления :-)

Поместите папку с MMP внутрь проекта.

Создайте внутри нее файл config.ini (описание конфига: http://www.antonoff.info/development/mysql-migration-with-php-project )

Создайте начальную миграцию ( ./migration.php schema )

В других установках вашего проекта накатите начальную миграцию ( ./migration.php init )

Изменяйте БД, и создавайте новые миграции ( ./migration.php create )

Чтобы мигрировать на последнюю версию, при получении новых миграций выполните (./migration.php migrate)

Просматривайте список доступных миграций (./migration.php list)

Мигрируйте на произвольную версию ( ./migration.php migrate 2 August 2010 )

VN:R_U [1.9.5_1105]
Rating: 0 (from 0 votes)

Прокомментировать

Вы должны быть авторизованы для комментирования.

Партнеры

Microsoft ITONLINE Group ScrimTrek IT Trainings

© Careerlab, ITONLINE GROUP 2012 Команда Software People

+7 (495) 933-01-33

team@softwarepeople.ru