问题的根源:在运行主服务器上创build从服务器的所有指令都要求flush tables with read lock 。 我们使用MyISAM,所以我们不能只使用 – 单个事务来获得一致的表数据。
奴隶失败的各种“正常”的原因 – 平均每周一次。 所以我把这个站点取消了,用读locking主表db,mysqldump(单个事务,带主logging),push到slave,复位master(用log对象),启动slave等。
要做到这一点没有主停机时间,我已经基本上尝试了相同的步骤,然后使用START SLAVE UNTIL – 然后暂停实时数据库几秒钟,而我运行SELECT MASTER_POS_WAIT(); 在奴隶。 我似乎不能让奴隶赶回去。
什么是从下面的步骤缺less(或不必要的),让从DB再次赶上主? 一个简单的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;
有两种select
备选#1:使用XtraBackup
它能够在运行的主机上复制MyISAM和InnoDB。
替代scheme#2:多次运行rsync
您可以在主服务器上对/ var / lib / mysql运行rsync,并将其复制到从服务器上的/ var / lib / mysql。 当然,我会多次运行rsync。 在最后的rsync之前,你应该运行带读锁的FLUSH TABLES。 在复制之前,确保你的软件都是二进制日志,并从头开始。
在运行任何东西之前,请确保在/etc/my.cnf中包含类似以下内容的二进制日志写入主服务器和从服务器上的/ var / lib / mysql:
[mysqld] log-bin=mysql-bin
如果您不想在主服务器上closuresMySQL,请尝试运行此脚本:
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};"
在数据和索引页面被caching的时候,我比较保守一些。 就个人而言,我更喜欢在几个rsyncs而不是FLUSH TABLES WITH READ LOCK之后closuresmysql。 这个脚本的另一种替代方法是closures最后一个rsync的mysql脚本。
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}"
你可以相信这些数字,因为你是从主人手中复制的。 现在你已经拥有主日志和位置了,你可以在slave上启动mysql,并使用刚才报告的日志文件和日志位置来设置复制。
试一试 !!!
警告
如果你有任何InnoDB数据,你应该在尝试rsync之前约1小时进行设置:
SET GLOBAL innodb_max_dirty_pages_pct = 0;
这将导致InnoDB更快地从InnoDB缓冲池中分发未提交的数据。
如果您的数据目录位于允许快照的文件系统上(例如ZFS或LVM),则可以在MySQL处于“closures”状态时创build快照,获取主信息并解锁表。 快照通常只需要几秒钟。