Все действия я произвожу в консоли, но ничего не мешает сделать из этого bash скрипт. Суть простая — копируем нижеприведенный текст в блокнот, меняем переменные в первых строках и поэтапно подсовываем нашему любимому интерпритатору. Итак начинаем:
Для удобства определяем переменные для работы. Действия производим на мастере.
MASTER=10.0.9.2 SLAVE=10.0.5.26 R_USER=replica R_PASS=replicapassword
Далее в общем-то классика: нам нужно запомнить позицию и бинарный лог-файл на котором сейчас находится чтение, потом сделать резервную копию. Чтобы эти данные были актуальны на момент окончания резервного копирования, мы заблокируем базу данных. Но есть сложность — в случае с большими обычно испльзуется mysqlhotcopy, но у нас база разношерстная и в ней присутствует innodb. Кроме того заказчика дешевле выключить сервер на 2 минуты, чем делать его доступным только на чтение на 10-15. Поэтому применяем древнее как мамонт ноухау в виде tar`а! Последовательность и логика бекапа от этого никоим образом не меняется.
echo "SET GLOBAL read_only = on;" | mysql -h$MASTER POS=$(echo "show master status;" | mysql -h$MASTER | grep -v DB) POS_FILE=$(echo $POS| cut -d ' ' -f 1) POS_POS=$(echo $POS| cut -d ' ' -f 2) /etc/init.d/mysqld stop cd /var/lib/mysql/ && tar cf /tmp/allbase.mysql.tar ./ /etc/init.d/mysqld start
Поскольку у нас вместо дампа таровский архив, восстанавливать его придется двумя командами. Первой заливаем, второй разархивируем.
rsync /tmp/allbase.mysql.tar root@$SLAVE: -e "ssh -oPort=2204" --progress
#На ведомом сервере выполняем:
service mysqld stop cd /var/lib/mysql && rm -r * && tar xvf /root/allbase.mysql.tar service mysqld start
Запускаем репликацию:
echo "change master to master_password='$R_PASS', master_host='$MASTER', master_user='$R_USER', master_log_file='$POS_FILE', master_log_pos=$POS_POS;" | mysql -h$SLAVE echo "start slave;" | mysql -h$SLAVE
Проверяем что все ОК
# echo "show slave status \G" | mysql -h$SLAVE |grep Running Slave_IO_Running: Yes Slave_SQL_Running: Yes
Советы из опыта:
- Бинарные логи лучше всего хранить в отдельном от баз месте. Так можно избежать лишних затрат на архивирование.
- Настройки innodb на мастере и на ведомом сервере должны совпадать:
# cat /etc/mysql/my.cnf | grep ^innodb
Создание пользователя для репликации:
-
GRANT REPLICATION SLAVE ON *.* TO 'replica'@'ip' IDENTIFIED BY 'password';
- Самые «дорогие» операции нужно минимизировать, в нашем случае нет ничего дороже простоя — чтобы увеличить время архивирования, желательно выключить все что может лишний раз диск. Перед архивированием проверить свободен ли он например камандами dstat или atop.
- Если у вас программисты индусы — рекомендую репликацию перевести в режим ROW-based. Это незначительно увеличит нагрузку на сеть и цпу, но избавит от трудностей связанных с тем что один и тот же stateiment запрос отработает по разному на мастере и слейве. Репликация будет жить!
cat /etc/mysql/my.cnf |grep binlog_format binlog_format=ROW
- Финальный копипаст:
MASTER=10.0.9.2 SLAVE=10.0.5.26 R_USER=replica R_PASS=replicapassword echo "SET GLOBAL read_only = on;" | mysql -h$MASTER POS=$(echo "show master status;" | mysql -h$MASTER | grep -v DB) POS_FILE=$(echo $POS| cut -d ' ' -f 1) POS_POS=$(echo $POS| cut -d ' ' -f 2) mysqldump -h$MASTER --all-databases > alldb.sql echo "SET GLOBAL read_only = off;" | mysql -h$MASTER mysql -h$SLAVE < alldb.sql echo "change master to master_password='$R_PASS', master_host='$MASTER', master_user='$R_USER', master_log_file='$POS_FILE', master_log_pos=$POS_POS;" | mysql -h$SLAVE echo "start slave;" | mysql -h$SLAVE echo "show slave status \G" | mysql -h$SLAVE |grep Running