web-dev-qa-db-ja.com

マスターダウンタイムなしでMySQLスレーブレプリケーションがリセットされました(MyISAMを使用)

問題の根本:実行中のマスターでスレーブを作成するためのすべての手順で、flush tables with read lockが必要です。 MyISAMを使用しているため、単一のトランザクションを使用して一貫性のあるテーブルデータを取得することはできません。

スレーブは、あらゆる種類の「通常の」理由で失敗します。平均して、週に1回程度です。そのため、サイトを停止し、テーブルを読み取りロックでマスターデータベースをフラッシュし、mysqldump(単一トランザクション、マスターレコードを使用)、スレーブにプッシュ、マスターをリセット(ログ位置を使用)、スレーブを開始します。

マスターダウンタイムなしでこれを行うには、基本的に同じ手順を試し、次にSTART SLAVE UNTILを使用します。次に、SELECT MASTER_POS_WAIT();を実行している間、ライブデータベースを数秒間一時停止します。奴隷に。そうすれば、奴隷に追いつくようには思えない。

スレーブ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;
6

2つの選択肢があります

代替#1:使用 XtraBackup

実行中のマスターにMyISAMとInnoDBをコピーできます。

代替#2:rsyncを複数回実行します

マスターの/ var/lib/mysqlに対してrsyncを実行し、スレーブの/ var/lib/mysqlにコピーすることができます。もちろん、rsyncを数回実行します。最後のrsyncまで、読み取りロック付きのFLUSHTABLESを実行する必要があります。コピーする前に、すべてのバイナリログをホースし、最初から始めることを確認してください。

何かを実行する前に、/ etc/my.cnfに次のようにして、マスターとスレーブの両方でバイナリログが/ var/lib/mysqlに書き込まれていることを確認してください。

[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};"

これを行っている間、データとインデックスページがキャッシュされるという点で私はもう少し保守的です。個人的には、FLUSH TABLES WITH READ LOCKではなく、いくつかのrsyncの後にmysqlをシャットダウンすることを好みます。このスクリプトの別の代替手段は、最後の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}"

これらの番号は、マスターから個人的にコピーしたため、信頼できます。マスターログと位置がわかったので、スレーブでmysqlを起動し、報告されたばかりのログファイルとログ位置を使用してレプリケーションをセットアップできます。

試してみる !!!

警告

InnoDBデータがある場合は、rsyncを試行する約1時間前にこれを設定する必要があります。

SET GLOBAL innodb_max_dirty_pages_pct = 0;

これにより、InnoDBはコミットされていないデータをInnoDBバッファープールからより速くページアウトします。

5
RolandoMySQLDBA

スナップショットを許可するファイルシステム(ZFS OR LVMなど)にdatadirがある場合は、MySQLが「ダウン」しているときにスナップショットを作成し、マスター情報を取得してから、テーブルのロックを解除できます。スナップショットは通常、数秒しかかかりません。

3
Ladadadada