MySQL 從屬複製重置,沒有主停機時間(使用 MyISAM)
問題的根源:在所有關於在正在執行的主機上創建從機的指令中,都需要
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;
有兩種選擇
替代方案 #1:使用XtraBackup
它能夠在執行的 master 上複製 MyISAM 和 InnoDB。
備選方案#2:多次執行 rsync
您可以在主伺服器上對 /var/lib/mysql 執行 rsync 並將其複製到從伺服器上的 /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};"
在執行此操作時,我在記憶體數據和索引頁面方面更加保守。就個人而言,我更喜歡在幾次 rsync 之後關閉 mysql,而不是 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
這就是來自 master 的 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 數據,你應該在嘗試 rsync 之前大約 1 小時進行設置:
SET GLOBAL innodb_max_dirty_pages_pct = 0;
這將導致 InnoDB 更快地從 InnoDB 緩衝池中分頁出未送出的數據。