Stellen Sie eine einzelne MySQL-Datenbank auf einem ausgelasteten Master-Slave-replizierten System wieder her


10

Suchen Sie nach einer Strategie oder einem Tool für die Wiederherstellung einer einzelnen Datenbank zu einem bestimmten Zeitpunkt in einem ausgelasteten replizierten System.

Ich habe 12 Datenbanken, die auf 2 MySQL 5.0.77-Servern in einer vom Master-Slave replizierten Konfiguration ausgeführt werden. Täglich wird ein vollständiger Speicherauszug des schreibgeschützten Slaves erstellt, und es sind inkrementelle SQL-Speicherauszüge verfügbar, wobei diese Sicherungen außerhalb des Standorts erfolgen und der Replikationsstatus überwacht wird.

Bearbeiten: Tabellen sind eine Mischung aus InnoDB und myISAM, daher sind keine motorspezifischen Lösungen verfügbar.

Bei einem vollständigen Ausfall des Master-Servers kann ich die Replikation unterbrechen und den Slave-Server hochstufen. Außerdem habe ich die Möglichkeit, einen neuen Server neu zu erstellen und aus der Offside-FULL-Sicherung heraus zu konfigurieren und dann die vom Slave stündlich entnommenen Differentiale anzuwenden.

Ich bin jedoch besorgt darüber, wie ich mit einem teilweisen Ausfall oder dem Ausfall einer einzelnen Datenbank umgehen soll. Ich kann mir zwei Szenarien vorstellen, die sehr wahrscheinlich sind.

  1. Datenbank 7 (zum Beispiel) wird beschädigt, bedient weiterhin einige Anforderungen, bis jemand bemerkt, dass sie beschädigt ist, oder Warnungen aus den Protokolldateien ...
  2. Einige Abfragen wie Drop-Datenbank, Drop-Tabelle, Abfrage vom Typ "Update where ..." borks eine einzelne Datenbank oder eine Teilmenge darin.

Im Moment habe ich eine Reihe von FULL-Dumps als FULL- $ DATE-all-database.sql.gz-Dateien und Differentiale, die auf die FULL-Dumps als DIFF- $ DATE-all-database.sql.gz angewendet werden können

Um die Datenbank 7 zu einem bestimmten Zeitpunkt wiederherzustellen, wäre ein Durchsuchen der FULL- und DIFF-Dateien sowie eine manuelle Anwendung dieser SQL erforderlich.

Wie soll ich vorgehen, um die Wiederherstellung eines der vorherigen DIFF-Dumps in der Master-Datenbank zu ermöglichen?

MUSS ich in einzelne Datenbankdateien sichern, dh

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

eher, als..

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

Was passiert mit dem Stammdaten-Binärprotokoll, wenn ich separate mysqldump-Dateien verwende, und sollte ich überhaupt --master-data für die Master-Server-Wiederherstellungsspeicherauszüge festlegen?

Antworten:


7

Wenn Ihre gesamte Datenbank nur InnoDB verwendet, habe ich gute Nachrichten.

Sie sollten die gesamte Datenbank parallel von einem Slave sichern.

Tatsächlich können Sie alle Datenbanken auf den gleichen Zeitpunkt zwingen.

Das Erste, woran Sie sich bei einem Slave erinnern sollten, ist, dass die binäre Protokollierung nicht aktiviert sein muss, wenn es sich nicht um einen Master für andere Slaves handelt.

Sie können die --master-dataOption nicht für parallele Speicherauszüge verwenden, da für jeden Speicherauszug in Zeile 22 jeder Speicherauszugsdatei eine andere Position geschrieben wird. Es ist besser, die letzte Protokolldatei des Masters aufzuzeichnen und den Slave zu positionieren, mit dem ausgeführt wird SHOW SLAVE STATUS\G. Auf diese Weise haben alle Datenbanken dieselbe Zeitpunktposition.

Sie können alle Datenbanken sammeln und den parallelen Speicherauszug der gesamten Datenbank skripten.

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

Wenn einfach zu viele Datenbanken vorhanden sind, sichern Sie diese 10 oder 20 gleichzeitig wie folgt:

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

Wenn Sie eine einzelne Tabelle wiederherstellen müssen, können Sie die Tabellen 20 gleichzeitig in der Größenreihenfolge parallel sichern .

Versuche dies:

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

Nachdem Sie über Skripte zum Speichern von Datenbanken oder einzelnen Tabellen verfügen, können Sie diese Daten nach eigenem Ermessen laden. Wenn Sie SQL aus den Binärprotokollen auf dem Master mysqlbinlogausführen müssen , können Sie die Position ot datetime verwenden und angeben und SQL in andere Textdateien ausgeben. Sie müssen nur eine Due Diligence durchführen, um die benötigte Datenmenge anhand der Zeitstempel zu ermitteln, über die die Bnary-Protokolle verfügen. Denken Sie daran, dass der Zeitstempel jedes Binärprotokolls im Betriebssystem das letzte Mal darstellt, als es geschrieben wurde.


brillante Antworten Danke. Ich denke, ein schreibgeschützter Slave auf xfs bietet mir viele Optionen, und Ihre Skripte haben wirklich geholfen.
Tom H

in dem Szenario, in dem ich eine massive Tabelle für den Master von einem Backup vom Slave wiederherstellen muss. Ich muss nur die Tabelle auf dem Master neu erstellen und alle Änderungen auf den Slave replizieren, auch wenn das 20 GB Daten sind. Wäre der Prozess 1) Deaktivieren von Schlüsseln, 2) Löschen der Tabelle auf Master und Slave 3) Wiederherstellen der Tabelle des Masters 4) Aktivieren von Schlüsseln --- und Lassen Sie den Master alle 20 GB auf den Slave replizieren?
Tom H

Wenn diese Datenbanken NICHT innodb sind, kann ich sie trotzdem parallel sichern?
Tom H

Ja, wenn Sie 1) Ausfallzeiten planen, 2) ausführen service mysql restart --skip-networking, 3) den parallelen Speicherauszug ausführen, 4) ausführen service mysql restart. Laden Sie dann die benötigten Tabellen neu.
RolandoMySQLDBA

Vermutlich, wenn der Zweck des Neustarts darin bestand, das Schreiben von Netzwerkverbindungen in die Datenbank zu verhindern, konnte ich den gleichen Effekt erzielen, indem ich iptables i.e. iptables -I INPUT -p tcp --dport 3306 -j DROPeth0 und lo
Tom H am
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.