- Подробности
-
Категория: PHP. Базы данных
Репликация MySQL на одном компьютере
Предупреждение. Если Вы не знакомы с репликацией в mysql, то вряд ли поймёте что-нибудь из ниженаписанного, Вам следует сперва ознакомиться с документацией
по репликации и по
запуску нескольких серверов mysql на одном компьютере.
Прелюдия. Понадобилось мне организовать двухстороннюю репликацию БД на двух mysql-серверах, запущенных на одной машине (для обхода блокировки myisam-таблиц). Казалось бы ничего сложного и особенного тут нет, учитывая то, что я знаю как запускать несколько mysql-серверов на одной машине и как организовать репликацию БД между двумя разными машинами. Но задача оказалась не самой простой. Не буду рассказывать, как в течение целого дня бился с конфигами, сколько вариантов запуска перепробовал и т.д., а просто напишу про подводные камни:
Подводный камень №1. У mysql есть параметры master-host, master-port, но нет параметра master-socket, поэтому когда я для первого сервера написал
master-host = localhost
master-port = 3307,
он цеплялся не к 127.0.0.1:3307, а к /tmp/mysql.sock, т.е. к самому себе, а не ко второму серверу. Причём в логах информация о том, куда он на самом деле цепляется случайно появилась только когда я там сильно нахимичил.
Обход этой проблемы — написать master-host = 127.0.0.1.
Подводный камень №2. Даже просле того, как я в my.cnf изменил master-host на 127.0.0.1, система ни хрена не заработала. Тут причина в том, что оказывается параметр master-host и некоторые другие параметры репликации считываются из основного конфига только в том случае, если что-то не в порядке с файлом master.info (он создаётся автоматом в каталоге данных), например, он просто отсутствует, а если он существует, то master-host считывается оттуда, и серверу положить, что я там поменял в my.cnf. В документации об этом сказано, но я это нашёл уже после того, как сам выяснил путём эксперимента… надо было выделить это красным жирным шрифтом, блин.
Обход этой проблемы — отредактировать вручную, либо, что проще, удалить master.info, не забыв перед этим остановить сервер mysql. При удалении потеряется оперативная инфа по репликации — текущий файл журнала — так что надо быть осторожным, безопаснее всё же отредактировать.
Что в итоге получилось. Вот кусок my.cnf, относящийся к делу, с которым всё работает замечательно (версия mysql 4.0.18):
################
# MySQL server 1
[mysqld1]
port = 3306
socket = /tmp/mysql.sock
datadir = /data/mysql1
pid-file = /data/mysql1/mysqld.pid
user = mysql
# replication
log-bin
server-id = 1
binlog-do-db = test
master-host = 127.0.0.1
master-port = 3307
master-user = replicator
master-connect-retry = 10
replicate-do-db = test
################
################
# MySQL server 2
[mysqld2]
port = 3307
socket = /tmp/mysql2.sock
datadir = /data/mysql2
pid-file = /data/mysql2/mysqld.pid
user = mysql
# replication
log-bin
server-id = 2
binlog-do-db = test
master-host = localhost
master-port = 3306
master-user = replicator
master-connect-retry = 10
replicate-do-db = test
################
На первом сервере следует сделать:
GRANT REPLICATION SLAVE ON *.* TO replicator@localhost;
на втором:
GRANT REPLICATION SLAVE ON *.* TO replicator@127.0.0.1;
О производительности (вместо заключения). Как видите, для второго сервера я оставил master-host = localhost, это вполне правомерно, т.к. он будет соединяться с /tmp/mysql.sock, т.е. к первому серверу, а нам туда и надо. Вроде бы как обмен через unix domain около двух раз быстрее, чем через сетевые сокеты. Вряд ли это может сильно повлиять на производительность репликации, тем более, что в большинстве случаев она реализуется между двумя разными машинами через сеть. Но несмотря на это смущает то, что разработчики mysql не предположили случая репликации на одном компьютере и не реализовали параметр master-socket. Написал им feature-request по этому поводу, посмотрим что скажут…