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

Корень проблемы: во всех инструкциях по созданию ведомого на работающем мастере требуется flush tables with read lock, Мы используем MyISAM, поэтому мы не можем просто использовать одну транзакцию для получения согласованных данных таблицы.

Раб терпит неудачу по разным "нормальным" причинам - в среднем примерно раз в неделю. Поэтому я отключаю сайт, сбрасываю таблицу с блокировкой чтения master db, mysqldump (отдельная транзакция, с основной записью), push to slave, сбрасываю master (с позициями журнала), запускаю slave и т. Д.

Чтобы сделать это без простоя мастера, я попытался в основном те же шаги, а затем использовать START SLAVE UNTIL - затем на несколько секунд приостановить работу живой базы данных, пока я запускаю 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;

2 ответа

Решение

Есть две альтернативы

АЛЬТЕРНАТИВА № 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 после нескольких rsyncs вместо 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 "выключен", получить основную информацию и затем разблокировать таблицы. Снимок обычно занимает всего несколько секунд.

Другие вопросы по тегам