MySQL 从属复制重置,没有主宕机时间(使用 MyISAM)

Jon*_*ler 6 mysql mysql-replication master-slave

问题的根源:在正在运行的主机上创建从机的所有说明中都需要flush tables with read lock. 我们使用MyISAM,所以我们不能只使用--single transaction 来获得一致的表数据。

奴隶因各种“正常”原因而失败——平均每周一次。所以我关闭了站点,使用读取锁定主数据库刷新表,mysqldump(单个事务,带有主记录),推送到从属,重置主(带有日志位置),并启动从属等。

为了在不停机的情况下做到这一点,我尝试了基本相同的步骤,然后使用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;
Run Code Online (Sandbox Code Playgroud)

Rol*_*DBA 5

有两种选择

替代方案 #1:使用XtraBackup

它能够在正在运行的主服务器上复制 MyISAM 和 InnoDB。

替代方法 #2:多次运行 rsync

您可以在主服务器上针对 /var/lib/mysql 运行 rsync 并将其复制到从属服务器上的 /var/lib/mysql。当然,我会多次运行 rsync。在最后的 rsync 之前,您应该运行 FLUSH TABLES WITH READ LOCK。在复制之前,请确保您管理所有二进制日志并从头开始。

在运行任何东西之前,请确保在 /etc/my.cnf 中包含类似以下内容的二进制日志在主从上的 /var/lib/mysql 中写入:

[mysqld]
log-bin=mysql-bin
Run Code Online (Sandbox Code Playgroud)

如果您不想在主服务器上关闭 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};"
Run Code Online (Sandbox Code Playgroud)

在执行此操作时,我在缓存数据和索引页方面更加保守。就个人而言,我更喜欢在几次 rsync 后关闭 mysql,而不是使用带读锁的 FLUSH TABLES。此脚本的另一种替代方法是以下脚本,它为最终 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
Run Code Online (Sandbox Code Playgroud)

这就是来自 master 的 rsync 部分的全部内容。奴隶呢???

在slave上启动mysql之前,需要有master的日志文件和日志位置。你复制的二进制日志有你需要的,尤其是最后一个二进制日志。这是你如何在奴隶上获得它:

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}"
Run Code Online (Sandbox Code Playgroud)

您可以信任这些数字,因为您亲自从主人那里复制了它们。现在你有了主日志和位置,你可以在从服务器上启动 mysql 并使用刚刚报告的日志文件和日志位置设置复制。

试一试 !!!

警告

如果你有任何 InnoDB 数据,你应该在尝试 rsync 之前大约 1 小时设置它:

SET GLOBAL innodb_max_dirty_pages_pct = 0;
Run Code Online (Sandbox Code Playgroud)

这将导致 InnoDB 更快地从 InnoDB 缓冲池中调出未提交的数据。