Mysql-Replication

MySQL 從屬複製重置,沒有主停機時間(使用 MyISAM)

  • April 1, 2015

問題的根源:在所有關於在正在執行的主機上創建從機的指令中,都需要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 緩衝池中分頁出未送出的數據。

引用自:https://serverfault.com/questions/288140