Назад | Перейти на главную страницу

Сброс ведомой репликации MySQL без простоя ведущего (с использованием MyISAM)

Корень проблемы: Во всех инструкциях по созданию ведомого на работающем мастере требуется 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 находится в «неактивном состоянии», получить основную информацию и затем разблокировать таблицы. Снимок обычно занимает всего несколько секунд.