Миграция Facebook на MySQL 8.0

Миграцияfacebookнаmysql80

MySQL , база данных с открытым исходным кодом, разработанная Oracle, поддерживает некоторые из самые важные рабочие нагрузки. Мы активно разрабатываем новые функции MySQL для поддержки наших меняющихся требований. Эти функции меняют множество различных областей MySQL, включая клиентские коннекторы, механизм хранения, оптимизатор и репликацию. Каждая новая основная версия MySQL требует значительного времени и усилий для переноса наших рабочих нагрузок. Задачи включают:

  • Перенос нашего пользовательского функции новой версии
  • Обеспечение совместимости репликации между основными версиями
  • Минимизация изменений, необходимых для существующих запросов приложений
  • Исправление падения производительности, которое не позволяет серверу поддерживать наши рабочие нагрузки

Наше последнее крупное обновление версии MySQL 5.6 потребовало больше года для развертывания. Когда была выпущена версия 5.7, мы все еще находились в процессе разработки нашего механизма хранения LSM-Tree, MyRocks , в версии 5.6. Поскольку обновление до 5.7 при одновременном создании нового механизма хранения значительно замедлило бы прогресс MyRocks, мы решили остаться с 5.6, пока MyRocks не будет завершен. MySQL 8.0 был анонсирован, когда мы завершали развертывание MyRocks на нашем уровне обслуживания пользовательской базы данных (UDB).

Эта версия включала в себя убедительные функции, такие как параллельная репликация на основе набора записей и словарь транзакционных данных, обеспечивающий поддержку атомарного DDL. Для нас переход на 8.0 также принесет функции 5.7, которые мы упустили, в том числе Document Store. Версия 5.6 приближалась к концу, и мы хотели оставаться активными в сообществе MySQL, особенно в нашей работе над механизмом хранения MyRocks. Усовершенствования в версии 8.0, такие как мгновенный DDL, могут ускорить изменение схемы MyRocks, но нам нужно было использовать кодовую базу 8.0, чтобы использовать ее. Учитывая преимущества обновления кода, мы решили перейти на версию 8.0. Мы рассказываем, как мы справились с нашим проектом миграции на 8.0, и о некоторых сюрпризах, которые мы обнаружили в процессе. Когда мы изначально оценивали масштаб проекта, было ясно, что переход на 8.0 будет даже сложнее, чем переход на 5.6 или MyRocks.

  • В то время в нашей настроенной ветке 5.6 было более 1, 700 код патчей для порта 8.0. Когда мы переносили эти изменения, в кодовую базу 5.6 были добавлены новые функции и исправления Facebook MySQL, которые отодвинули стойку ворот еще дальше.
  • У нас есть много серверов MySQL, работающих в производстве, обслуживающих большое количество разнородных приложений. У нас также есть обширная программная инфраструктура для управления экземплярами MySQL. Эти приложения выполняют такие операции, как сбор статистики и управление резервными копиями серверов.
  • Обновление с 5.6–8.0 полностью пропускает 5.7. API-интерфейсы, которые были активны в 5.6, были бы устаревшими в 5.7 и, возможно, были бы удалены в 8.0, что потребовало бы от нас обновления любого приложения с использованием теперь удаленных API.
  • Ряд функций Facebook не был совместим с аналогичными функциями в версии 8.0 и требовал отказа от поддержки и перехода вперед.
  • Для работы в версии 8.0 потребовались улучшения MyRocks, включая собственное разбиение на разделы и восстановление после сбоя.

Патчи кода

Сначала мы настроили ветку 8.0 для сборки и тестирования в наших средах разработки. Затем мы начали долгий путь по портированию патчей из нашей ветки 5.6. Когда мы начали, было более 1 0900, но мы смогли организовать их на несколько основных категорий. У большей части нашего пользовательского кода были хорошие комментарии и описания, поэтому мы могли легко определить, нужен ли он по-прежнему приложениям или его можно отбросить. Функции, которые были активированы специальными ключевыми словами или уникальными именами переменных, также упрощали определение релевантности, поскольку мы могли выполнять поиск по кодовым базам наших приложений, чтобы найти варианты их использования. Несколько патчей были очень малоизвестными и требовали детективной работы – рыться в старых проектных документах, сообщениях и / или комментариях к обзору кода – чтобы понять их историю.

Мы отсортировали каждый патч по одному из четырех сегментов:

  1. Удаление: функции, которые больше не использовались или имели эквивалентную функциональность в 8.0, переносить не нужно.
  2. Сборка / Клиент: Несерверные функции, которые поддерживают нашу среду сборки и модифицированные инструменты MySQL, такие как mysqlbinlog, или дополнительные функции, такие как API асинхронного клиента были перенесены.
  3. Сервер, не относящийся к MyRocks: особенности на сервере mysqld, которые не были связаны с нашим механизмом хранения MyRocks, были перенесены.
  4. Сервер MyRocks: были перенесены функции, поддерживающие механизм хранения MyRocks.

Мы отслеживали статус и актуальную историческую информацию каждого патча usi ng и записали наши рассуждения при выпуске патча. Несколько патчей, обновляющих одну и ту же функцию, были сгруппированы для переноса. Патчи, перенесенные и зафиксированные в ветке 8.0, были аннотированы информацией о фиксации версии 5.6. Несоответствия в статусе переноса неизбежно возникнут из-за большого количества исправлений, которые нам нужно было просмотреть, и эти примечания помогли нам их решить.

Каждая из категорий клиентов и серверов, естественно, стала важной вехой в выпуске программного обеспечения. После того как все изменения, связанные с клиентом, были перенесены, мы смогли обновить наши клиентские инструменты и код коннектора до версии 8.0. После того, как все функции сервера, не относящиеся к MyRocks, были перенесены, мы смогли развернуть MySQL 8.0 для серверов InnoDB. Завершение работы над функциями сервера MyRocks позволило нам обновить установки MyRocks.

Некоторые из наиболее сложных функций потребовали значительных изменений для версии 8.0. , и в некоторых областях были серьезные проблемы совместимости. Например, форматы событий бинарного журнала исходной версии 8.0 были несовместимы с некоторыми из наших пользовательских модификаций 5.6. Коды ошибок, используемые функциями Facebook 5.6, конфликтуют с кодами, назначенными новым функциям восходящей версией 8.0. В конечном итоге нам потребовалось исправить наш сервер 5.6, чтобы обеспечить прямую совместимость с 8.0.

На завершение ушло несколько лет. перенос всех этих функций. К тому времени, как мы добрались до конца, мы оценили более двух 390 исправлений и перенесено 1, 500 из них на 8.0.

Путь миграции

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

Facebook MySQL 8 animation

Мы начали с наборов реплик, состоящих из 5.6 первичных / 5.6 вторичных, а конечной целью были наборы реплик с 8.0 первичными / 8.0 вторичными. Мы следовали плану, аналогичному плану миграции UDB MyRocks .

  1. Для каждого набора реплик создайте и добавьте вторичные реплики 8.0 через логическую копию с помощью mysqldump. Эти вторичные серверы не обслуживают трафик чтения приложений.
  2. Включить трафик чтения на второстепенные версии 8.0.
  3. Разрешить преобразование экземпляра 8.0 в основной.
  4. Отключить экземпляры 5.6 для чтения трафика.
  5. Удалите все экземпляры 5.6.

Каждый набор реплик может проходить каждый из вышеперечисленных шагов независимо и оставаться на одном шаге. столько, сколько нужно. Мы разделили наборы реплик на гораздо более мелкие группы, которыми руководили на каждом этапе перехода. Если мы обнаружили проблемы, мы могли вернуться к предыдущему шагу. В некоторых случаях наборы реплик могли достичь последнего шага перед запуском других.

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

Репликация на основе строк

В рамках миграции на 8.0 мы решили стандартизировать использование построчной репликации (RBR). Некоторые функции 8.0 требовали RBR, и это упростило наши усилия по переносу MyRocks. Хотя большинство наших наборов реплик MySQL уже использовали RBR, те, которые все еще выполняли репликацию на основе операторов (SBR), не могли быть легко преобразованы. Эти наборы реплик обычно содержат таблицы без ключей высокой мощности. Полное переключение на RBR было целью, но длинный хвост работы, необходимый для добавления первичных ключей, часто имел более низкий приоритет, чем другие проекты.

Следовательно, мы сделали RBR требованием для версии 8.0. После оценки и добавления первичных ключей к каждой таблице мы переключились на последний набор реплик SBR в этом году. Использование RBR также дало нам альтернативное решение для решения проблемы приложения, с которой мы столкнулись, когда мы переместили некоторые наборы реплик на первичные версии 8.0, которые будут обсуждаться позже.

Проверка автоматизации

Большая часть процесса миграции 8.0 включала тестирование и проверку сервера mysqld с помощью нашей инфраструктуры автоматизации и запросов приложений.

По мере роста нашего парка MySQL росла и инфраструктура автоматизации, которую мы используем для управления серверами. Чтобы обеспечить совместимость всей нашей автоматизации MySQL с версией 8.0, мы вложили средства в создание тестовой среды, в которой использовались наборы тестовых реплик с виртуальными машинами для проверки поведения. Мы написали интеграционные тесты для canary каждой части автоматизации для работы как в версии 5.6, так и в версии 8.0, и проверили их правильность. Во время выполнения этого упражнения мы обнаружили несколько ошибок и различий в поведении.

Поскольку каждая часть инфраструктуры MySQL проверялась на соответствие нашим 8.0 мы обнаружили и исправили (или обошли) ряд интересных проблем:

  1. Программное обеспечение, которое анализировало текстовый вывод из журнала ошибок, вывода mysqldump или команд показа сервера, легко ломалось. Незначительные изменения в выводе данных сервера часто выявляли ошибки в логике анализа инструмента.
  2. Параметры сортировки 8.0 по умолчанию utf8mb4 приводили к несоответствиям параметров сортировки между нашими экземплярами 5.6 и 8.0. Таблицы 8.0 могут использовать новый utf8mb4 _ 0900 сопоставления даже для операторов создания, сгенерированных таблицей создания шоу 5.6, поскольку схемы 5.6 используют utf8mb4_general_ci явно не указывают сопоставление. Эти различия таблиц часто вызывали проблемы с инструментами репликации и проверки схемы.
  3. коды ошибок для некоторых сбоев репликации изменились, и нам пришлось исправить нашу автоматизацию, чтобы правильно их обрабатывать.
  4. Словарь данных версии 8.0 устарел .frm-файлы таблиц, но некоторые средства автоматизации использовали их для обнаружения изменений схемы таблиц.
  5. Нам пришлось обновить нашу автоматизацию для поддержки динамических привилегий, представленных в 8.0.

Проверка приложения

Мы хотели, чтобы переход для приложений был максимально прозрачным, но некоторые запросы приложений снижают производительность или не работают на 8.0.

Для миграции MyRocks мы создали теневое тестирование MySQL framework, который захватывает производственный трафик и воспроизводит его в тестовых экземплярах. Для каждой рабочей нагрузки приложения мы построили тестовые экземпляры на 8.0 и воспроизвели для них запросы теневого трафика. Мы зафиксировали и зарегистрировали ошибки, возвращаемые с сервера 8.0, и обнаружили некоторые интересные проблемы. К сожалению, не все эти проблемы были обнаружены при тестировании. Например, тупиковая ситуация транзакции была обнаружена приложениями во время миграции. Мы смогли откатить эти приложения до 5.6 временно, пока мы исследовали различные решения.

  • Новые зарезервированные ключевые слова были введены в 8.0, и некоторые из них, такие как группы и ранг, противоречили популярным именам столбцов таблицы и псевдонимам, используемым в запросах приложений. Эти запросы не экранировали имена с помощью обратных кавычек, что приводило к ошибкам синтаксического анализа. Приложения, использующие программные библиотеки, которые автоматически экранировали имена столбцов в запросах, не сталкивались с этими проблемами, но не все приложения использовали их. Устранить проблему было несложно, но потребовалось время, чтобы отследить владельцев приложений и кодовые базы, генерирующие эти запросы.
  • Также было обнаружено несколько несовместимостей REGEXP между 5.6 и 8.0.
  • Несколько приложений попали в транзакция с повторяющимся чтением взаимоблокировки с участием вставить… на дублирующем ключе запросы на InnoDB. В 5.6 была ошибка, которая была исправлена ​​в версии 8.0, но исправление увеличило вероятность взаимоблокировок транзакций. Проанализировав наши запросы, мы смогли решить их, снизив уровень изоляции. Эта опция была доступна нам, так как мы перешли на построчную репликацию.
  • Наши пользовательские функции 5.6 Document Store и JSON не были совместимы с 8.0. Приложениям, использующим Хранилище документов, требовалось преобразовать тип документа в текст для миграции. Для функций JSON мы добавили 5.6-совместимые версии на сервер 8.0, чтобы приложения могли перейти на API 8.0 позже.

Наши запросы и тестирование производительности сервера 8.0 выявили несколько проблем, которые необходимо было решить почти немедленно.

  • Мы обнаружили новые конфликтные точки мьютекса вокруг кеша ACL. Когда большое количество соединений было открыто одновременно, все они могли блокироваться при проверке списков ACL.
  • Аналогичное противоречие было обнаружено при доступе к индексу binlog, когда присутствует много файлов binlog и при высокой скорости записи binlog файлы часто меняются.
  • Не удалось выполнить несколько запросов, связанных с временными таблицами. Запросы возвращали неожиданные ошибки или выполнялись так долго, что время ожидания истекало.

Использование памяти по сравнению с 5.6 увеличилось, особенно для наших экземпляров MyRocks, потому что InnoDB в версии 8.0 должен быть загружен. По умолчанию настройки performance_schema активировали все инструменты и потребляли значительный объем памяти. Мы ограничили использование памяти, включив только небольшое количество инструментов и внося изменения в код, чтобы отключить таблицы, которые нельзя было отключить вручную. Однако не вся увеличенная память распределялась с помощью performance_schema. Нам нужно было изучить и изменить различные внутренние структуры данных InnoDB, чтобы еще больше уменьшить объем памяти. Эти усилия позволили снизить использование памяти 8.0 до приемлемого уровня.

Что дальше

Миграция 8.0 пока заняла несколько лет. Мы преобразовали многие из наших наборов реплик InnoDB для работы полностью на 8.0. Большинство оставшихся находятся на разных этапах пути миграции. Теперь, когда большинство наших пользовательских функций перенесено на 8.0, обновление до минорных выпусков Oracle стало сравнительно проще, и мы планируем идти в ногу с последними версиями.

Пропуск основной версии, такой как 5.7, приводит к проблемам, которые необходимо решить при миграции.

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

Во-вторых, это значительно труднее обнаружить изменения API, потому что 5.7 могла бы предоставить нашим клиентам приложения предупреждения об устаревании для устранения потенциальных проблем. Вместо этого нам нужно было запустить дополнительные теневые тесты, чтобы найти сбои, прежде чем мы сможем перенести производственные рабочие нагрузки. Использование клиентского программного обеспечения mysql, которое автоматически экранирует имена объектов схемы, помогает уменьшить количество проблем совместимости.

Поддержка двух основных версий в пределах одного реплики установить сложно. После того, как набор реплик повысит свой первичный статус до экземпляра версии 8.0, лучше всего как можно скорее отключить и удалить реплики версии 5.6. Пользователи приложений склонны открывать для себя новые функции, которые поддерживаются только версией 8.0, например utf8mb4 _ 0900 сопоставления, и их использование может разбить поток репликации между экземплярами 8.0 и 5.6.

Несмотря на все препятствия на пути миграции, мы уже увидели преимущества использования версии 8.0. Некоторые приложения выбрали раннее преобразование в 8.0, чтобы использовать такие функции, как хранилище документов и улучшенную поддержку даты и времени. Мы думали, как поддерживать такие функции механизма хранения, как Instant DDL, на MyRocks. В целом, новая версия значительно расширяет возможности MySQL @ Facebook.