Блог bitmanager

Система хранения паролей Rattic: миграция на PostgreSQL

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

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

Сконвертировав базу из MySQL в PostgreSQL скриптом py-mysql2pgsql, я поправил настройки web-интерфейса, обновил страницу и подивился серьезному приросту скорости работы. Казалось бы, мелочь, а приятно. Но рано радовался. Пароли прекрасно смотрелись, искались, открывались, но отредактировать не удавалось ни один, Error 500 и все тут. Тут я погрустнел. Потому что, судя по логу, не сконвертировались все foreign ключи и была какая-то проблема с форматом даты, что и давало пресловутую ошибку 500. Ну, что ж, расчехляем скальпель и начинаем препарировать. Rattic написан с использованием Django, поэтому план был примерно такой: экспортировать данные через manage.py dumpdata, сбросить и переинициализировать таблицы, затем в чистые таблицы залить данные.

И началась веселая пробежка по граблям:
  1. Грабли первые — никогда не пересоздавайте первичные миграции. То есть, если посмотреть manage.py migrate --list,там можно видеть, что у каждого используемого компонента уже есть initial миграция, и она стоит первой. Я создал еще по одной, и, в итоге, при инициализации таблицы происходила ошибка SQL и все останавливалось. А удалять их очень сложно, надо найти все модули, в которых создались кривые миграции и удалить их оттуда.
  2. Грабли вторые — не доверяйте скрипту преобразования. У вас нет возможности проверить, все ли он правильно перенес, потому исходно сразу предполагайте, что данные повреждены. При этом дамп данных создается прекрасно, но залить его назад потом не получится.
  3. Грабли третьи — не накатывайте данные скриптом py-mysql2pgsql поверх подготовленной миграциями структуры. Это бесполезно, потому что скрипт не учитывает foreign ключи, отключить их в postgres базе очень сложно и загрузка данных будет постоянно падать из-за нарушения связности.

Правильный порядок действий в итоге такой:
  1. Вернуться на базу MySQL.
  2. Сделать дамп данных командой manage.py dumpdata --all.
  3. Перейти на PostgreSQL. Имеется в виду переключить Django в конфиге на использование базы PostgreSQL. При этом база уже должна существовать и на нее должны быть определены права.
  4. Выполнить manage.py syncdb. Это создать необходимые базовые таблицы для работы Django.
  5. Выполнить manage.py migrate. Это создаст и подготовит все остальные таблицы.
  6. Выполнить manage.py loaddata. Это загрузит данные в базу, которые были сохранены ранее.

Вот и все, данные успешно, а, главное, полностью, перетекли в базу PostgreSQL.

Записки сисадмина