AWS DMS для миграции баз данных
На одном из проектов перед нами встала задача миграции базы данных с MySQL 5.7 на MySQL 8. При этом, даунтаймы в работе системы крайне не желательны. Хотим поделиться нашим опытом использования AWS Database Migration Service для миграции базы данных без даунтайма.
Хотим поделиться нашим опытом миграции базы данных без даунтайма с использованием AWS DMS (Database Migration Service). Перед нами стояла задача мигрировать базу данных с MySQL 5.7 на MySQL 8 на проекте, где даунтаймы крайне не желательны. На самом деле, бесперебойной работой должны были быть обеспечены всего несколько API методов проекта, что позволило нам включить Maintenance Mode на некоторых частях системы.
Самым первым вариантом миграции было быстрое создание и разворачивание дампа базы данных с последующим переключением проекта на хост новой базы данных. К сожалению, нам такой вариант не подошёл из-за того, что размер исходной базы данных довольно большой ~10 GB. К тому же, было необходимо проверить целостность данных после восстановления дампа снятого с MySQL 5.7 и развернутого на MySQL 8 версии перед переключением на новую версию.
Теория AWS Database Migration Service
Сервис AWS DMS позволяет произвести миграцию данных между базами быстро и безопасно, используя в качестве исходных и целевых баз данных различные распространенные БД. Также AWS DMS позволяет производить непрерывную репликацию данных, что нам очень пригодилось. Нет никаких технических ограничений на время выполнения задачи, к тому же данный сервис позволяет выполнить миграцию очень дешево, как заявляет AWS, миграция 1 терабайта данных, обойдется всего лишь в 3 USD.
Концепция сервиса DMS очень проста в использовании и имеет три основных компонента: Конечные точки, задачи и экземпляры репликации.
Конечные точки — Endpoints
Определяют подключения к источникам данных и целям. В качестве конечных точек можно использовать различные базы данных, и даже S3.
Задачи — Tasks
В задаче можно определить какую конечную точку использовать как источник данных, а какую как цель. Также можно настроить, каким образом выполнять миграцию, полную, репликацию, или и то и другое вместе. Также в задаче можно настроить, какие схемы и таблицы необходимо включить или исключить из миграции. Задача позволяет настроить преобразование схемы, таблицы или столбца. Таким образом, можно во время миграции преобразовать одно имя столбца в другое. Но именно данными манипулировать не получится.
Экземпляры репликации — Replication instance
AWS DMS не является бессерверным, и для выполнения задач требуется EC2 инстанс. Нет необходимости в поддержке и управлении этим инстансом через SSH, поэтому и подключиться к этому инстансу возможности нет, он находится полностью под управлением DMS.
Подготовка к миграции
Хотя данный процесс с DMS и выглядит простым делом, тем более с однородной миграцией MySQL to MySQL, все равно мы столкнулись с рядом проблем, которые пришлось решать, и на подготовку и проверку данных потратили довольно много времени.
Идея миграции полностью соответствовала задачам, которые должен решать DMS. Её можно кратко описать в пяти шагах:
- Создаем целевую базу данных MySQL 8 в RDS
- Мигрируем все данные из RDS MySQL 5.7 исходной БД
- Включаем репликацию данных
- Проверяем корректность скопированных данных и данных, которые реплицировались за определенный период времени
- Переключаем доменное имя хоста на новую базу
Весь процесс миграции был обкатан на нашем Development окружении, поэтому большинство проблем мы обнаружили в процессе подготовки. AWS DMS позволяет перед стартом провести валидацию схемы базы данных на пригодность к миграции. На этапе валидации мы обнаружили сразу три небольшие проблемы:
- Все LOB (large objects) столбцы должны быть NULLABLE. В нашей базе данных имелось несколько полей с LONGTEXT типом. Данная проблема решается простым преобразованием колонки в NULLABLE поле. Причина такого требования кроется в механизме миграции, AWS DMS сначала создает все строки с пустыми LOB полями, а потом отдельно записывает их.
- Не должно быть таблиц без первичного ключа. В нашей базе данных имелась таблица без первичного ключа, а без него AWS DMS не может выполнять миграцию. В нашем случае мы создали составной первичный ключ, т.к. это была таблица, в которой комбинация из трех ее столбцов образовывала уникальную запись.
- При валидации DMS показал множество предупреждений связанных с TIME и ENUM полями, пометив их как неподдерживаемый тип данных. Но в дальнейшем эксперименты показали, что миграция этих полей происходит нормально, т.к DMS поля с неподдерживаемым типом переносит просто как текстовые поля, а MySQL, в свою очередь, корректно конвертирует время и Enum поля в виде текста и корректно вставляет данные.
Во время настройки AWS DMS, первым что приходит в голову это настроить два эндпоинта, и запустить задачу на копирование данных из одной базы в другую. Мы так и сделали, миграция прошла успешно, но в итоге выяснилось что DMS не клонирует внешние ключи, триггеры, дефолтные значения у полей и т.д. Поэтому после непродолжительного поиска информации, поняли, что рекомендуется сначала создать дамп базы без данных, только схему, накатить его на целевую БД и только после этого запускать миграцию.
В процессе миграции и репликации триггеры, созданные в целевой базе данных, начали срабатывать при вставке данных в новую базу, что значительно замедляло процесс и создавало дубликаты записей в таблицах, т.к. одни и те же триггеры срабатывали в исходной и целевой базах данных. Поэтому триггеры, до переключения хоста базы на новую пришлось удалить из целевой БД и создать сразу же после переключения хоста БД на новую.
Проверка корректности мигрированных данных
Мы должны были убедиться в том, что данные корректны и полностью совпадают в исходной и целевой БД, и это оказалось непростой задачей. Что бы это провернуть, было принято решение сравнивать дампы баз. Для этого мы одновременно создали дампы с двух баз данных и решили прогнать их через DiffTool. Но ни один Diff Tool не мог справиться с файлом размером в 10GB, поэтому разделили файлы дампов на части меньшего размера, по 100 MB, с которыми уже можно было работать.
В процессе проверки была обнаружена разница, связанная c не полной синхронностью создания дампов и небольшой задержкой в репликации. По отличающимся данным можно было легко это понять.
Но больше никаких серьезных проблем обнаружено не было, и можно было с уверенностью сказать, что мы полностью готовы к миграции.
Production в ожидании переезда
Так как процесс репликации базы никак не влияет на основную систему, мы заранее мигрировали базу в MySQL 8 и в течение некоторого времени уже работала репликация. Набрав достаточно реплицированных изменений, мы выполнили проверку с помощью Diff Tool, не выявили никаких новых проблем по сравнению с Development окружением. Нам только оставалось сделать несколько последних самых критичных для системы шагов, переключение и восстановление триггеров.
Настроили Healthcheck с помощью JMeter, который будет выполнять запросы на API методы, которые ни в коем случае не должны подвергнуться даунтайму.
До переключения MySQL хоста мы заранее задеплоили скрипты, восстанавливающие триггеры, чтобы после оперативно их восстановить. Так как работоспособность админки системы не так важна, как API, мы временно включили на WebUI нашей админки Maintenance Mode, чтобы сократить количество текущих подключений к базе данных. Maintenance Mode – это специальный режим работы системы, который мы можем включить на определенную ее часть во время проведения работ, в этот момент пользователь видит соответствующую заглушку с просьбой попробовать зайти на сайт позже.
После переключения хоста на новый MySQL 8, JMeter не выявил никаких даунтаймов. Понаблюдав за снижением количества подключений к старой БД, после того как убедились что подключения к старой БД отсутствуют, вернули триггеры и выключили Maintenance Mode.
Заключение
Как итог, можно сказать что миграция прошла успешно, и по плану даунтайма не заметил ни один клиент нашего API.
Хоть и существуют множество полезных инструментов, таких как AWS DMS, всегда будьте очень аккуратны в применении этих инструментов, и всегда лучше убедиться и перепроверить, прежде, чем применять что-то на Production.