web-dev-qa-db-ja.com

使用中のマスター/スレーブ複製システムで単一のmysqlデータベースを回復する

ビジー状態のレプリケートされたシステムで単一のデータベースを特定の時点にリカバリするための戦略またはツールを探します。

マスタースレーブ複製構成の2つのMySQL 5.0.77サーバーで実行されている12のデータベースがあります。読み取り専用スレーブのフルダンプが毎日取得され、これらのバックアップがオフサイトにある、使用可能な増分SQLダンプがあり、レプリケーションステータスが監視されます。

編集:テーブルはInnoDBとmyISAMの混合であるため、エンジン固有のソリューションは利用できません。

したがって、マスターサーバーに完全な障害が発生した場合、レプリケーションを中断してスレーブサーバーを昇格させることができます。また、新しいサーバーを再構築してオフサイドのフルバックアップから構成し、スレーブから1時間ごとに取得した差分を適用することもできます。

ただし、部分的な障害、または単一のデータベースの障害に対処する方法を心配しています。かなりありそうな2つのシナリオが考えられます。

  1. データベース7(たとえば)が破損し、誰かがそれが壊れていることに気づくまで、またはログファイルからアラートを出すまで、いくつかの要求を処理し続けます...
  2. データベースの削除、テーブルの削除、「更新場所...」タイプのクエリなどの一部のクエリは、単一のデータベース、またはその中の一部のサブセットを作成します。

現時点では、FULL- $ DATE-all-databases.sql.gzファイルとして多数のフルダンプがあり、DIFF- $ DATE-all-databases.sql.gzとしてフルダンプに適用できる差分があります

データベース7を特定の時点に復元するには、FULLファイルとDIFFファイルを使用したgrepと、そのSQLを手動で適用する必要があります。

マスターデータベースへの以前のDIFFダンプの1つに回復できるようにするには、どうすればよいですか?

個々のデータベースファイルにバックアップする必要がありますか?

mysqldump --databases "database1" | gzip > database1.sql.gz
mysqldump --databases "database2" | gzip > database2.sql.gz
mysqldump --databases "database3" | gzip > database3.sql.gz

のではなく..

mysqldump --master-data --lock--all-databases --all-databases | gzip > all-databases.sql.gz

個別のmysqldumpファイルを使用する場合、マスターデータのバイナリログはどうなりますか?マスターサーバーのリカバリダンプに--master-dataを設定する必要がありますか?

10
Tom H

すべてのデータベースがInnoDBのみを使用している場合、良いニュースがあります。

すべてのデータベースをスレーブから並行してダンプする必要があります。

実際、すべてのデータベースを同じ時点に強制することができます。

スレーブについて最初に覚えておくべきことは、スレーブが他のスレーブのマスターでない場合は、バイナリログを有効にする必要がないことです。

各ダンプは、各ダンプファイルの22行目に異なる位置に書き込まれるため、並列ダンプに--master-dataオプションを使用することはできません。マスターの最後のログファイルを記録し、SHOW SLAVE STATUS\Gを使用して実行されたスレーブを配置することをお勧めします。このように、すべてのデータベースは同じ時点の位置を持っています。

すべてのデータベースを収集し、すべてのデータベースの並列ダンプをスクリプト化できます。

DBLIST=/tmp/ListOfDatabasesToParallelDump.txt
BACKUP_BASE=/backups
BACKUP_DATE=`date +"%Y%m%d_%H%M%S"`
BACKUP_HOME=${BACKUP_BASE}/${BACKUP_DATE}
mkdir ${BACKUP_HOME}
cd ${BACKUP_HOME}

mysql -h... -u... -p... -e"STOP SLAVE;"
mysql -h... -u... -p... -e"SHOW SLAVE STATUS\G" > ${SSS}
LOGFIL=`cat ${SSS} | grep "Relay_Master_Log_File" | awk '{print $2}'`
LOGPOS=`cat ${SSS} | grep "Exec_Master_Log_Pos"   | awk '{print $2}'`
echo "Master was at ${LOGFIL} Position ${LOGPOS} for this Backup" > Master_Log_FilePos.txt

mysql -h... -u... -p... -AN -e"SELECT schema_name FROM information_schema.schemata WHERE schema_name NOT IN ('information_schema','mysql','performance_schema')" > ${DBLIST}

for DB in `cat ${DBLIST}` 
do 
    mysqldump -h... -u... -p... --hex-blob --routines --triggers ${DB} | gzip > ${DB}.sql.gz & 
done 
wait 

mysql -h... -u... -p... -e"START SLAVE;"

データベースが多すぎる場合は、次のように一度に10個または20個ずつダンプします。

DBLIST=/tmp/ListOfDatabasesToParallelDump.txt
SSS=/tmp/ShowSlaveStatusDisplay.txt
BACKUP_BASE=/backups
BACKUP_DATE=`date +"%Y%m%d_%H%M%S"`
BACKUP_HOME=${BACKUP_BASE}/${BACKUP_DATE}
mkdir ${BACKUP_HOME}
cd ${BACKUP_HOME}

mysql -h... -u... -p... -e"STOP SLAVE;"
mysql -h... -u... -p... -e"SHOW SLAVE STATUS\G" > ${SSS}
LOGFIL=`cat ${SSS} | grep "Relay_Master_Log_File" | awk '{print $2}'`
LOGPOS=`cat ${SSS} | grep "Exec_Master_Log_Pos"   | awk '{print $2}'`
echo "Master was at ${LOGFIL} Position ${LOGPOS} for this Backup" > Master_Log_FilePos.txt

mysql -h... -u... -p... -AN -e"SELECT schema_name FROM information_schema.schemata WHERE schema_name NOT IN ('information_schema','mysql','performance_schema')" > ${DBLIST}

COMMIT_LIMIT=20
COMMIT_COUNT=0    
for DB in `cat ${DBLIST}` 
do 
    mysqldump -h... -u... -p... --hex-blob --routines --triggers ${DB} | gzip > ${DB}.sql.gz & 
    (( COMMIT_COUNT++ ))
    if [ ${COMMIT_COUNT} -eq ${COMMIT_LIMIT} ]
    then
        COMMIT_COUNT=0
        wait
    fi
done 
wait 
if [ ${COMMIT_COUNT} -gt 0 ]
then
    wait
fi

mysql -h... -u... -p... -e"START SLAVE;"

単一のテーブルを回復する必要がある場合は、サイズ順で一度にtables 20を並列ダンプできます。

これを試して:

TBLIST=/tmp/ListOfTablesToParallelDump.txt
SSS=/tmp/ShowSlaveStatusDisplay.txt
BACKUP_BASE=/backups
BACKUP_DATE=`date +"%Y%m%d_%H%M%S"`
BACKUP_HOME=${BACKUP_BASE}/${BACKUP_DATE}
mkdir ${BACKUP_HOME}
cd ${BACKUP_HOME}

mysql -h... -u... -p... -e"STOP SLAVE;"
mysql -h... -u... -p... -e"SHOW SLAVE STATUS\G" > ${SSS}
LOGFIL=`cat ${SSS} | grep "Relay_Master_Log_File" | awk '{print $2}'`
LOGPOS=`cat ${SSS} | grep "Exec_Master_Log_Pos"   | awk '{print $2}'`
echo "Master was at ${LOGFIL} Position ${LOGPOS} for this Backup" > Master_Log_FilePos.txt

mysql -h... -u... -p... -AN -e"SELECT CONCAT(table_schema,'.',table_name) FROM information_schema.tables WHERE table_schema NOT IN ('information_schema','mysql','performance_schema') ORDER BY data_length" > ${DBLIST}

COMMIT_LIMIT=20
COMMIT_COUNT=0    
for DBTB in `cat ${TBLIST}` 
do
    DB=`echo "${DBTB}" | sed 's/\./ /g' | awk '{print $1}'`
    TB=`echo "${DBTB}" | sed 's/\./ /g' | awk '{print $2}'`
    DUMPFILE=$DB-{DB}-TBL-${TB}.sql.gz
    mysqldump -h... -u... -p... --hex-blob --routines --triggers ${DB} ${TB} | gzip >  ${DUMPFILE} & 
    (( COMMIT_COUNT++ ))
    if [ ${COMMIT_COUNT} -eq ${COMMIT_LIMIT} ]
    then
        COMMIT_COUNT=0
        wait
    fi
done 
wait 
if [ ${COMMIT_COUNT} -gt 0 ]
then
    wait
fi

mysql -h... -u... -p... -e"START SLAVE;"

データベースまたは個々のテーブルをダンプするスクリプトを作成したので、そのデータを自由にロードできます。マスターのバイナリログからSQLを実行する必要がある場合は、mysqlbinlogを使用して日時の位置を指定し、SQLを他のテキストファイルに出力できます。バイナリログのタイムスタンプから必要なデータ量を見つけるために、十分な注意を払う必要があります。 OS内のすべてのバイナリログのタイムスタンプは、最後に書き込まれた時刻を表していることに注意してください。

7
RolandoMySQLDBA