Корень проблемы: Во всех инструкциях по созданию ведомого на работающем мастере требуется flush tables with read lock
. Мы используем MyISAM, поэтому мы не можем просто использовать --single transaction для получения согласованных данных таблицы.
Раб выходит из строя по разным «нормальным» причинам - в среднем примерно раз в неделю. Итак, я отключаю сайт, сбрасываю таблицу с блокировкой чтения для главной базы данных, mysqldump (одиночная транзакция, с основной записью), нажимаю на ведомое устройство, сбрасываю ведущее устройство (с позициями в журнале) и запускаю ведомое устройство и т. Д.
Чтобы сделать это без простоев мастера, я попробовал в основном те же шаги, а затем использовал START SLAVE UNTIL
- затем приостановить live db на несколько секунд, пока я запускаю SELECT MASTER_POS_WAIT (); на раб. Тогда я не могу заставить раба догнать меня.
Что отсутствует (или не нужно) из приведенных ниже шагов, чтобы подчиненная БД снова догнала мастер? Был бы простой start slave
работай?
#!/bin/bash
##
mysqldump --allow-keywords --add-drop-table --comments --extended-insert --master-data \
--debug-info --single-transaction -u $LOCALDB_USER_NAME -p$LOCALDB_PASS $LOCALDB_NAME > $DBFILENAME
## get master position from file for use later
echo
echo "############# MASTER STATUS #############"
cat $DBFILENAME | grep "CHANGE MASTER"
echo
echo "compressing"
gzip $DBFILENAME
echo "sending to $REMOTE_SERVER"
[...]
echo "uncompresing remote db"
sudo ssh $REMOTE_SERVER_USERNAME@$REMOTE_SERVER "cd /tmp && gunzip /tmp/$COMPRESSED_DBFILENAME "
echo "loading external db"
sudo ssh $REMOTE_SERVER_USERNAME@$REMOTE_SERVER "mysql -u $REMOTEDB_USER_NAME -p$REMOTEDB_PASS $REMOTEDB_NAME -e \"STOP SLAVE;\" "
sudo ssh $REMOTE_SERVER_USERNAME@$REMOTE_SERVER "mysql -u $REMOTEDB_USER_NAME -p$REMOTEDB_PASS $REMOTEDB_NAME -e \"RESET SLAVE;\" "
sudo ssh $REMOTE_SERVER_USERNAME@$REMOTE_SERVER "mysql -u $REMOTEDB_USER_NAME -p$REMOTEDB_PASS $REMOTEDB_NAME -e \"FLUSH LOGS;\" "
sudo ssh $REMOTE_SERVER_USERNAME@$REMOTE_SERVER "mysql -u $REMOTEDB_USER_NAME -p$REMOTEDB_PASS $REMOTEDB_NAME < /tmp/$DBFILENAME"
echo "remote import completed"
# CHANGE MASTER TO MASTER_HOST=' ', MASTER_USER='', MASTER_PASSWORD='', MASTER_LOG_FILE='mysql-bin.042025', MASTER_LOG_POS=73160995;
# START SLAVE UNTIL MASTER_LOG_FILE='mysql-bin.042025', MASTER_LOG_POS=73160995;
## on master
## FLUSH TABLES WITH READ LOCK;
## SHOW MASTER STATUS;
## select from above
## on slave:
## SELECT MASTER_POS_WAIT('mysql-bin.042136', 165900463);
## on master
## UNLOCK TABLES;
Есть две альтернативы
АЛЬТЕРНАТИВА №1: Используйте XtraBackup
Он способен копировать MyISAM, а также InnoDB на работающем мастере.
АЛЬТЕРНАТИВА # 2: запустить rsync несколько раз
Вы можете запустить rsync для / var / lib / mysql на ведущем устройстве и скопировать его в / var / lib / mysql на ведомом устройстве. Конечно, я бы несколько раз запустил rsync. До последнего rsync вы должны запускать FLUSH TABLES WITH READ LOCK. Перед копированием убедитесь, что вы пропустите все двоичные журналы и начнете с нуля.
Перед запуском чего-либо убедитесь, что двоичные журналы записаны в / var / lib / mysql как на главном, так и на подчиненном устройстве, имея что-то вроде следующего в /etc/my.cnf:
[mysqld]
log-bin=mysql-bin
Если вы не хотите выключать MySQL на главном сервере, попробуйте запустить этот сценарий:
mysql -u... -p... -e"SET GLOBAL innodb_max_dirty_pages_pct = 0; RESET MASTER;"
RSYNCSTOTRY=7
cd /var/lib/mysql
X=0
while [ ${X} -lt ${RSYNCSTOTRY} ]
do
X=`echo ${X}+1|bc`
rsync -r * slaveserver:/var/lib/mysql/.
sleep 60
done
mysql -u... -p... -e"FLUSH TABLES WITH READ LOCK; SELECT SLEEP(86400);"
sleep 60
SLEEPID=`mysql -u... -p... -e"SHOW PROCESSLIST;" | grep "SELECT SLEEP(86400)" | awk '{print $1}'`
rsync -r * slaveserver:/var/lib/mysql/.
mysql -u... -p... -e"KILL ${SLEEPID};"
Я немного более консервативен с точки зрения кэширования страниц данных и индекса при этом. Лично я предпочитаю выключать mysql после нескольких rsync вместо FLUSH TABLES WITH READ LOCK. Другой альтернативой этому сценарию может быть следующий сценарий, который отключает mysql для последнего rsync:
mysql -u... -p... -e"RESET MASTER;"
RSYNCSTOTRY=7
cd /var/lib/mysql
X=0
while [ ${X} -lt ${RSYNCSTOTRY} ]
do
X=`echo ${X}+1|bc`
rsync -r * slaveserver:/var/lib/mysql/.
sleep 60
done
service mysql stop
rsync -r * slaveserver:/var/lib/mysql/.
service mysql start
Это все, что касается части rsync от мастера. Что насчет Раба ???
Перед тем, как запустить mysql на ведомом устройстве, вам необходимо получить файл журнала и позицию журнала от ведущего устройства. Вам нужны скопированные двоичные журналы, особенно последний двоичный журнал. Вот как это получается на раб:
cd /var/lib/mysql
for X in `ls -l mysql-bin.0* | awk '{print $9}'`
do
LOGFIL=${X}
done
LOGPOS=`ls -l ${LOGFIL} | awk '{print $5}'`
echo "Master Log File ${LOGFIL} Position ${LOGPOS}"
Этим цифрам можно доверять, потому что вы скопировали их лично у мастера. Теперь, когда у вас есть главный журнал и позиция, вы можете запустить mysql на подчиненном сервере и настроить репликацию, используя файл журнала и позицию в журнале, о которых только что было сообщено.
Попробуйте !!!
ПРЕДОСТЕРЕЖЕНИЕ
Если у вас есть данные InnoDB, вы должны установить это примерно за 1 час до попытки rsync:
SET GLOBAL innodb_max_dirty_pages_pct = 0;
Это заставит InnoDB быстрее выгружать незафиксированные данные из пула буферов InnoDB.
Если у вас есть каталог данных в файловой системе, которая позволяет делать снимки (например, ZFS ИЛИ LVM), вы можете создать снимок, когда MySQL находится в «неактивном состоянии», получить основную информацию и затем разблокировать таблицы. Снимок обычно занимает всего несколько секунд.