Здравствуйте.
Хочу поделиться опытом миграции боевой базы данных с MySQL 5.0 на Percona Server 5.5 под нагрузкой почти без отрыва от производства.
Опишу вкратце эволюцию нашей базы до текущего состояния
База у нас древняя, пережила несколько апгрейдов MySQL. Начинали с MySQL 3.x. С ростом нагрузки, уже на MySQL 5.0, настроили репликацию и подключили еще один сервер для чтения. Тогда мы это делали стандартными средствами MySQL, без привлечения xtrabackup — полностью блокировали сервер на время создания мастер-дампа и вывешивали на сайтах заглушки.
Затем встала следующая проблема — на томе с данными стало заканчиваться место. Плюс InnoDB-хранилище исторически располагалось в одном файле. Было рассмотрено много вариантов решения. Начиная от размещения базы на iSCSI-томе и заканчивая перетыканием в рейд более емких дисков, расширением на них volume group / logical volume с последующим расширением файловой системы.
В качестве временного варианта решили подключить iSCSI-том из виртуалки под VMWare vCloud (не реклама, честно!). vCloud стоит у нас под боком.
Начали с эксперимента на slave. Эксперимент прошел удачно, и какое-то время второй read-only MySQL держал хранилище на iSCSI-томе.
Стали всерьез задумываться о переезде базы полностью в облако
В качестве эксперимента подключили вторым слейвом на чтение сервер в vCloud. Перенесли на него всю нагрузку с первого слейва. По производительности виртуальный сервер выигрывал с хорошим отрывом. Сказывалось более мощное железо у хостов vCloud. Переключили нагрузку назад. Стали думать.
В этот момент случилось странное мистическое событие. Спустя нескольких часов после завершения эксперимента с нагрузкой на виртуальном сервере в датацентре произошла хитрая авария, в результате которой обесточилось несколько серверов, в том числе физический слейв. В relay log, находящийся на iSCSI-томе у физического слейва, попал мусор. Репликация остановилась.
Самым логичным действием в этой ситуации было переключение на облачный слейв, что мы и сделали.
Таким образом мы уже находились одной read-only ногой в vCloud. Надо было перетаскивать master.
Переехать решили на Percona 5.5, так же на два сервера, но с потабличным разбиением InnoDB-хранилища.
Основным ограничением при переезде была невозможность останавливать базу на сколько-нибудь продолжительное время.
Поскольку речь идет о разбиении InnoDB-хранилища на таблицы, простым копированием данных обойтись не получится. Надо вливать новую базу из дампа.
Чтобы получить мастер-дамп, надо залочить 125-гиговую базу на время более часа. Это неприемлемо на боевой базе. Мы решили бэкапить мастер при помощи xtrabackup, поднимать на получившемся слепке сервер, и снимать с него мастер-дамп.
Итак, ингредиенты
- Два старых боевых MySQL-5.0-сервера под нагрузкой. Назовем их 5.0-master и 5.0-slave.
- Два новых боевых Percona-5.5-сервера пока без нагрузки, данных и репликации. Назовем их 5.5-master и 5.5-slave.
- Один промежуточный MySQL-5.0-сервер для снятия дампа. Назовем его 5.0-Kenny.
Для разбиения InnoDB-хранилища по таблицам на новых серверах надо выставить опцию "innodb_file_per_table=1".
Поскольку речь идет об облаке, мы играючи поднимаем три недостающих сервера за пять минут.
В рамках программы по сокращению времени простоя до минимума мы решили не перенастраивать приложения для работы с новым мастером, а просто поднять ip старого мастера на новом сервере. Для этого необходимо, чтобы ip старого сервера был виден на новом мастере для всех клиентов. В нашем случае все пять серверов находятся в одной подсети, так что проблем с этим нет.
А теперь — последовательность действий
- С мастер-базы (5.0-master) снимаем дамп при помощи xtrabackup:
innobackupex --user=root --password=Yoo0edae _каталог_назначения_
Важно помнить, что чем больший объем данных вашей базы находится в MyISAM-таблицах, тем на большее время база будет заблокирована при финализации xtrabackup, так как MyISAM-таблицы копируются полностью во время финальной блокировки базы. В нашем случае MyISAM-данных практически нет, поэтому база находится в заблокированном состоянии всего несколько секунд.
- В полученном каталоге с данными есть файл xtrabackup_binlog_info — запоминаем из него позицию в бинлоге.
- Полученный слепок копируем на 5.0-Kenny (мы монтировали диск с Kenny по NFS на 5.0-Master, и указывали его в каталоге назначения при снятии данных xtrabackup-ом, так что данные на 5.0-Kenny появлялись в процессе работы xtrabackup). Там его подготавливаем:
innobackupex --apply-log _каталог_с_бэкапом_
- Останавливаем MySQL. вычищаем каталог с данными MySQL, в него копируем наш слепок:
innobackupex --copy-back _каталог_с_бэкапом_
Можно скопировать вручную. Тогда в MySQL-хранилище останется некоторый мусор от процесса резервирования. При необходимости выставляем правильного владельца на каталог с данными.
- Запускаем MySQL. Убеждаемся, что ошибок нет.
- С 5.0-Kenny снимаем дамп:
mysqldump --all-databases > mysql.dump
- Полученный дамп копируем на 5.5-master. Вливаем:
mysql < mysql.dump
- Рестартуем MySQL. Любуемся на гору ошибок в логе. Апгрейдим схему до версии 5.5:
mysql_upgrade --force
- Рестартуем MySQL. В логах должно быть чисто.
- Включаем репликацию, подключаем 5.5-master к бинлогу 5.0-master. Для этого сначала добавляем на 5.0-master пользователя для репликации (про server-id все ведь помнят, да?):
mysql> GRANT REPLICATION SLAVE ON *.* TO 'repl_master_55' IDENTIFIED BY 'slavepass'; mysql> FLUSH PRIVILEGES;
после чего на 5.5-master выполняем запрос:
mysql> CHANGE MASTER TO MASTER_HOST='master_host_name', MASTER_USER='repl_master_55', MASTER_PASSWORD='slavepass', MASTER_LOG_FILE='recorded_log_file_name', MASTER_LOG_POS=recorded_log_position; mysql> START SLAVE;
Значения MASTER_LOG_FILE и MASTER_LOG_POS берем из файла "xtrabackup_binlog_info".
- Убеждаемся, что репликация пошла:
mysql> SHOW SLAVE STATUSG
Наш 5.5-master какое-то время будет слейвом для 5.0-master. Для того чтобы запросы с 5.0-master попадали в бинлог на 5.5-master, на 5.5-master надо выставить опцию "log-slave-updates=1". По дефолту она равна нулю, то есть в бинлог попадают только локальные изменения.
- Снимаем с 5.5-master дамп при помощи xtrabackup. Копируем дамп на 5.5-slave.
- Поднимаем 5.5-slave, цепляем его к бинлогу 5.5-master.
Итого, у нас получается четыре сервера: два старых, но пока боевых MySQL 5.0, и два новых Percona 5.5 уже с актуальными данными.
- Переключаем всю read-only-нагрузку со старого 5.0-slave на новый 5.5-slave. Поскольку 5.5-slave реплицируется с 5.5-master, который в свою очередь реплицируется с 5.0-master, никто ничего не замечает. Полдела сделано — часть нагрузки у нас уже на новой связке.
Начинается самое интересное. Здесь находится точка невозврата. Начиная с этого момента, засекаем время простоя мастер-базы.
- Останавливаем MySQL на 5.0-master.
- Убеждаемся, что все данные из бинлога попали на 5.5-master
- Отлучаем 5.5-master от бинлога:
mysql> RESET SLAVE ALL;
- Останавливаем MySQL на 5.5-master
- На 5.0-master кладем сетевой интерфейс, по которому происходило общение приложений с базой, поднимаем этот ip на сервере, на котором у нас находится 5.5-master.
- Убеждаемся, что arp-таблица обновилась.
- Поднимаем 5.5-master. Убеждаемся, что MySQL слушает на новом ip.
- Перезапускаем приложения, использующие persistent-connect к базе.
Все
В нашем случае время простоя было около полутора минут. Бóльшую часть этого времени складывался 5.0-master. В принципе, можно было время простоя уменьшить еще сильнее, сбросив InnoDB-кэши перед остановкой баз.
vCloud показал себя с хорошей стороны. Производительность при переезде ощутимо выросла благодаря более мощному железу и значительно более шустрой дисковой подсистеме, так как виртуальный диск «размазан» по большому количеству физических носителей.
Автор: winduzoid