Репликация MySQL
Ниже собраны заметки и ссылки на тему репликации MySQL-баз данных.
Настройка репликации
Мастер-сервер
- Добавляем нужные опции в конфиге my.cnf на мастер-сервере:
[mysqld]
# Идентификатор сервера. На каждой связке серверов (как на мастерах, так и на слейвах) должен быть уникален.
# Является числом в диапазоне от 1 до 4294967295 (2^32-1)
server-id = 1
# Путь к бинарным логам, в которых сохраняются все изменения в базе данных мастер-сервера. Должно быть достаточно места под эти логи
log-bin = /var/lib/mysql/mysql-bin
# Сколько дней хранить бинарные логи на мастере. В некотором роде это еще и определяет, на сколько слейв может отстать от мастера
# expire_logs_days = 10
# Размер файла бинлога (каждого отдельного файла)
# max_binlog_size = 1024M
# Имя базы, для которой надо делать репликацию. При необходимости делать репликацию нескольких баз - повторить опцию с нужным именем базы
replicate-do-db = testdb
# Помимо этой опции, есть еще опции "обратного выбора" - для исключения выборки баз
# replicate-ignore-db=database_name
# а также опции для репликации отдельных таблиц (аналогично - выбрать одну/несколько; исключить одну/несколько, а также определение имен через wildcard'ы)
# Эта опция нужна на тот случай, если этот мастер-сервер является слейвом по отношению к другому - чтобы слейв для данного мастера (суб-слейв основного мастера) тоже получал обновления
# Может пригодиться при репликации мастер-мастер с одним слейвом
# log-slave-updates
- Даем права слейв-серверу делать репликацию с этого. Для этого в консоли mysql даем команду:
mysql> GRANT replication slave ON *.* TO "repluser"@"replhost" IDENTIFIED BY "replpass";
где:
- repluser - имя пользователя для подключения. Пользователь создается в момент выполнения команды.
- replhost - IP-адрес или домен хоста слейв-сервера, который будет подключаться к этому мастеру
- replpass - пароль для подключения
Ограничение на базу для репликации в grant replication вроде как не работает - т.е., разрешаем все, а в конфиге указываем только ту базу / базы, которые нужны
Перезапускаем сервер, после чего в консоли можно выполнить команду
mysql> SHOW MASTER STATUS;
которая покажет файл бинарного лога, с которым сейчас работает мастер и текущую позицию в логе, а также базу/базы, для которых делается репликация.
Slave-сервер
- Добавляем нужные опции в конфиге my.cnf на slave-сервере:
[mysqld]
# Идентификатор сервера для данной связки серверов - см. описание выше
server-id = 2
# Relay-логи - логи, скачанные с мастер-сервера
# Указываем путь для этих логов; должно быть достаточно места для их хранения.
# relay-log = /var/lib/mysql/mysql-relay-bin
# relay-log-index = /var/lib/mysql/mysql-relay-bin.index
# Имя базы, которую будем реплицировать
replicate-do-db = testdb
Перезапускаем сервер для применения изменений
Запуск репликации
На мастере блокируем таблицы на запись для получения полностью корректного дампа:
mysql> FLUSH TABLES WITH READ LOCK;
mysql> SET GLOBAL read_only = ON;
Сливаем дамп с сервера. Кое-где обычно еще пишут про то, что необходимо смотреть позицию и имя лога на мастере - это не обязательно и решается ключом --master-data для mysqldump, который запишет необходимую информацию в сам дамп:
mysqldump --master-data -hmasterhost -umasteruser -pmasterpass masterdbname > dump.sql
После этого пускаем мастер в работу:
mysql> SET GLOBAL read_only = OFF;
(хотя возникает мысль - а действительно ли нужно лочить базу при дампе? Как только начал делаться дамп с --master-data - в него кидается имя лога и позиция, а таблицы автоматически лочатся на запись - т.е. все то же самое, только в автоматическом режиме)
Далее заливаем дамп на слейв-сервер как обычно:
mysql -hslavehost -uslaveuser -pslavepass slavedbname < dump.sql
В данном случае slavedbname = masterdbname, хотя при желании можно сделать так, чтобы база реплицировалась уже под другим именем.
Указываем слейву адрес мастер-сервера:
mysql> CHANGE MASTER TO MASTER_HOST = "masterip", MASTER_USER = "repluser", MASTER_PASSWORD = "replpass";
где masterip - IP-адрес или домен мастер-сервера, а остальные опции - те, что указывались выше при настройке мастера. Имя лог-файла и позиция берется из дампа, но при желании их можно вручную указать через опции MASTER_LOG_FILE = "имя_лога", MASTER_LOG_POS = позиция
После этой команды информация о мастере сохраняется в файле master.info в каталоге баз данных mysql-сервера. При желании можно указать эти опции в конфиге слейв-сервера:
master-host = masterip
master-user = repluser
master-password = replpass
master-port = 3306
После этого запускаем slave-сервер через mysql-консоль:
mysql> START SLAVE;
Теперь можно проверить статус slave-сервера командой
mysql> SHOW SLAVE STATUS;
Из интересной информации там могут быть поля:
- Slave_IO_State: Waiting FOR master TO send event, Slave_IO_Running: Yes и Slave_SQL_Running: Yes - все работает хорошо :)
- Seconds_Behind_Master - на сколько слейв отстал от мастера. В нормальном режиме должен быть 0
...и прочая текущая информация вроде отсутствия ошибок, текущей позиции и имени лога сервера, лога слейва и т.п.
Разное
Для mysqldump есть 2 опции для вписывания имени лога и позиции в файл дампа: --master-data и --dump-slave. Вторая есть не везде:
root@import:~# mysqldump --help | grep 'dump-slave'
root@import:~# mysqldump --version
mysqldump Ver 10.13 Distrib 5.1.61, for portbld-freebsd8.2 (amd64)
а там, где есть - особо разницы в выполняемых действиях не вижу.
Update: нашел:
--dump-slave[=value] This option is similar to --master-data except that it is used to dump a replication slave server to produce a dump file that can be used to set up another server as a slave that has the same master as the dumped server. It causes the dump output to include a CHANGE MASTER TO statement that indicates the binary log coordinates (file name and position) of the dumped slave's master (rather than the coordinates of the dumped server, as is done by the --master-data option). These are the master server coordinates from which the slave should start replicating. This option was added in MySQL 5.5.3.
Все равно пока не ясно, зачем нужны 2 практически одинаковых опции, но:
- --dump-slave появился только недавно, это надо учитывать в скриптах.
- --master-data хочет master-логи.
Ошибки репликации
При работе репликации могут возникать ошибки - по какой-либо причине, например, ручном внесении данных на слейв-сервере.
Варианты решения:
1) Добавляем в конфиг слейв-сервера опцию для пропуска определенного типа ошибок, например:
skip-errors = 1062,1063
Перезапускаем сервер, после этого ошибки указанных типов будут игнорироваться
2) задать счетчик числа ошибок через mysql-консоль:
mysql> SET GLOBAL SQL_SLAVE_SKIP_COUNTER = 1;
mysql> START SLAVE;
Данный запрос установит счетчик пропуска ошибок равным единице (иными словами позволит пропустить одну ошибку).
Однако любой из вариантов предполагает, что после ошибки данные в базе слейв-сервера могут быть некорректны, поэтому лучше все же разобраться с ошибкой, залить на слейв дамп с бэкапа и запустить сервер заново.
В случае случайных ручных изменений данных на слейве можно добавить в конфиг опцию read-only
Ссылки
- Основы репликации Mysql
- Официальная документация по репликации
- Статья по репликации на ibm.com (Внимание! Опечатка! GRANT REPLICATION нужно делать только на мастере!)
- [1], [2], [3], [4], [5] - еще ряд статей по основам
- Master-master-репликация
- Мульти-мастер-репликация
- [6], [7], [8] - статьи по mysql-proxy
- [9], [10] - ошибки mysql-репликации
- Delayed replication