Миграция Redmine с MySQL на PostgreSQL

На этот раз рассмотрим перенос данных из MySQL в PostgreSQL, пригодный, пожалуй, для любых приложений, предоставляющих выбор из этих двух СУБД.

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

Рассмотрим эту стратегию миграции на примере Redmine.

1. Получение схемы базы данных

Схема базы данных - это её структура, то есть таблицы, индексы, ключи, без данных.

Установим дополнительно пакет, отвечающий за работу Redmine совместно с СУБД PostgreSQL:

# apt-get install redmine-pgsql

Для начала перейдём в каталог /etc/redmine/, в котором есть подкаталоги, соответствующие экземплярам redmine:

# cd /etc/redmine/

Скопируем каталог одного из экземпляров в другой каталог, создав таким образом новый экземпляр. В данном случае копируем экземпляр default и создаём на его основе экземпляр pgsql:

# rsync -rogp default/ pgsql/

Открываем файл /etc/redmine/pgsql/database.yml и заменяем в нём имя пользователя в поле username, имя базы данных в поле database и тип базы данных в поле adapter. У меня получился такой файл:

production:
  adapter: postgresql
  database: redmine_pgsql
  host: localhost
  port:
  username: redmine_pgsql
  password: password
  encoding: utf8

Теперь нужно создать соответствующего пользователя и базу данных:

# su - postgres
$ createuser -P redmine_pgsql
$ createdb -E UTF-8 -O redmine_pgsql redmine_pgsql
$ exit

Пустая база данных и пользователь созданы. Теперь нам нужно наполнить эту базу данных структурой и первичными данными. Для этого переходим в каталог /usr/share/redmine/, в котором находится Redmine, и запускаем команду миграции экземпляра pgsql, которая сделает всё необходимое:

# cd /usr/share/redmine
# rake db:migrate RAILS_ENV=production X_DEBIAN_SITEID=pgsql

Теперь, если всё прошло успешно, создаём резервную копию этой базы данных, но без собственно данных:

# su - postgres
$ pg_dump -s -d redmine_pgsql > redmine_pgsql.sql

Теперь можно удалить этого пользователя и его базу данных, от них нам больше ничего не нужно:

$ dropdb redmine_pgsql
$ dropuser redmine_pgsql
$ exit

Теперь можно удалить и каталог с настройками экземпляра pgsql:

# cd /etc/redmine
# rm -R pgsql

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

Сделать это можно вот так:

$ cat redmine_pgsql.sql | sed -e 's/^--.*$//g; s/^COMMENT .*$//; /^$/d; s/"//g; s/TO redmine_pgsql/TO redmine_default/g' > redmine_default.sql

Теперь нужно поделить файл redmine_default.sql на две части. Первый должен создать структуру базы данных без ограничений и внешних ключей, а второй - добавлять их. К счастью, стандартный дамп, созданный pg_dump, можно легко поделить на нужные нам части. Первая часть заканчивается запросами вида "ALTER TABLE ONLY ... ALTER COLUMN ... SET DEFAULT ...", а вторая часть начинается запросами вида "ALTER TABLE ONLY ... ADD CONSTRAINT ...". В результате должны получиться файлы redmine_default1.sql и redmine_default2.sql

Приведу ссылки на эти файлы: redmine_default1.sql и redmine_default2.sql Они соответствуют версии Remine, поставляющейся в репозиториях Debian Jessie (версии пакетов - 3.0~20140825-5). Если у вас именно эта версия Redmine, можно пропустить весь этот раздел и сразу воспользоваться этими файлами.

2. Собственно перенос данных

Если pgloader ещё не установлен, установим его:

# apt-get install pgloader

Теперь создадим файл redmine_default.sql с настройками миграции:

LOAD DATABASE
  FROM mysql://redmine_default:password@localhost/redmine_default
  INTO postgresql://redmine_default:password@localhost/redmine_default

WITH include no drop,
     truncate,
     create no tables,
     create no indexes,
     no foreign keys,
     reset sequences,
     data only

SET maintenance_work_mem TO '128MB',
    work_mem to '12MB'

BEFORE LOAD EXECUTE redmine_default1.sql

Теперь отключаем Redmine, чтобы данные не менялись в процессе переноса в новую СУБД:

# /etc/init.d/uwsgi stop redmine

Открываем файл с настройками подключения к базе данных мигрируемого экземпляра default. В данном случае это файл /etc/redmine/default/database.yml, который в данный момент настроен на использование MySQL. Нужно создать точно такого же пользователя и базу данных в PostgreSQL:

# su - postgres
$ createuser -P redmine_default
$ createdb -E UTF-8 -O redmine_default redmine_default
$ exit

Запускаем миграцию:

$ pgloader redmine_default.load

После миграции открываем снова файл с настройками подключения к базе данных мигрируемого экземпляра default. Это файл /etc/redmine/default/database.yml, заменяем в нём тип базы данных с mysql2 на postgresql.

Теперь можно запустить uwsgi, чтобы Redmine вновь стал доступен для пользователей. Тестируем, всё ли правильно работает. Дальше можно перенести другие экземпляры Redmine и по окончании миграции удалить пакет Redmine для работы с MySQL:

# apt-get purge redmine-mysql

Написать автору