Coding → Простой способ синхронизации структуры и данных MySQL при работе с Mercurial

Привет. Недавно перевёл работу на Mercurial и встала задача организовать синхронизацию MySQL. Погуглив, ничего простого и надёжного не было найдено, поэтому пришлось самому решать эту задачу.

Решение оказалось на удивление простым. Разделим задачу на две части: сохранение изменений базы данных, с последующим  коммитом и пушем в центральный репозиторий, и обновление структуры БД после апдейта. Тогда задание сводится к тому, чтобы перед коммитом(а точнее перед hg status) сделать дамп базы в определённый файл и закоммитить его. И затем после hg update нужно этот файл импортировать в базу, вместе с свежими изменениями.

Общее решение

Для решения проблемы воспользуемся хуками (подробнее). Заходим в папку .hg в нашем репозитории, и находим(или не находим, тогда создаём) там файл hgrс. Открываем его любимым редактором и вставляем туда следующий код:

[hooks]
pre-status = c:\path\to\mysql\bin\mysqldump.exe -u USERNAME -pUSERPSWD DBNAME > db\dump.sql

update = c:\path\to\mysql\bin\mysql.exe -u USERNAME -pUSERPSWD DBNAME < db\dump.sql

Если вы не понимаете указанные параметры, запустите mysqldump —help и почитайте мануал. Вкратце — заменяем USERNAME на имя пользователя MySQL(должен иметь права для дампа и импорта),  USERPSWD — на пароль этого пользователя и DBNAME на имя базы данных. Если хотите, можете поменять место хранения дампа(db\dump.sql, относительно корня репозитория). Пользователям не-windows систем может потребоваться поменять ещё и разделитель директорий на «/».

Всё. Теперь можно запустить hg status и увидеть, что Mercurial заметил изменения в дампе(после первого запуска появится файл с дампом, не забудьте добавить его в репозиторий командой hg add):

Решение для TortoiseHg

При использовании TortoiseHg не срабатывает хук «pre-status». Вызвано это тем, что команда «status» там вообще не запускается. Я не смог выяснить, какая команда там запускается при формировании списка изменённых файлов в окне «commit», поэтому пришлось вешать хук на сам коммит. В итоге в файл hgrc там нужно добавить немного изменённый код:

[hooks]
commit.a = c:\path\to\mysql\bin\mysqldump.exe -u USERNAME -pUSERPSWD DBNAME > db\ep.sql
commit.b = hg status

update = c:\path\to\mysql\bin\mysql.exe -u USERNAME -pUSERPSWD DBNAME < db\temp.sql

Теперь коммит будет проходить в два этапа — сначала изменённые файлы, затем срабатывает хук, и сразу коммитим изменённый дамп. Чуть менее удобно, но пока другого решения я не нашёл. Апдейт работает так же, как и в первом случае.

Спасибо за внимание. Как обычно, буду рад любым улучшениям и предложениям.

Полезные ссылки:

  • мануал по mercurial hooks
  • mysqldump.exe версии 5.1.5 для пользователей Денвера(там урезанная версия MySQL и нет этого файла)