recuperar una sola base de datos mysql en un sistema replicado maestro-esclavo ocupado

10

Buscando una estrategia o herramienta para lidiar con la recuperación de una única base de datos a un punto en el tiempo en un sistema replicado ocupado.

Tengo 12 bases de datos que se ejecutan en 2 servidores MySQL 5.0.77 en configuración replicada maestro-esclavo. Se realiza un volcado completo del esclavo de solo lectura diariamente, y hay volcados incrementales de SQL disponibles, con estas copias de seguridad fuera del sitio y se supervisa el estado de la replicación.

Editar: Las tablas son una mezcla de InnoDB y myISAM, por lo tanto, las soluciones específicas del motor no están disponibles.

Entonces, dado un fallo completo del servidor maestro, puedo romper la replicación y promover el servidor esclavo, también tengo la opción de reconstruir un nuevo servidor y configurarlo desde la copia de seguridad COMPLETA fuera de juego, y luego aplicar los diferenciales tomados por hora desde el esclavo.

Sin embargo, me preocupa cómo lidiar con una falla parcial o la falla de una sola base de datos. Puedo pensar en 2 escenarios que son bastante probables;

  1. la base de datos 7 (por ejemplo) se corrompe, continúa atendiendo algunas solicitudes hasta que alguien se da cuenta de que está dañada o alerta de los archivos de registro ...
  2. Algunas consultas, como la base de datos desplegable, la tabla desplegable, la consulta de tipo "actualizar donde ..." abrevia una sola base de datos o algún subconjunto en ella.

Por el momento, tengo un montón de volcados COMPLETOS como archivos FULL- $ DATE-all-database.sql.gz, y diferenciales que se pueden aplicar a los volcados FULL- DIFF- $ DATE-all-database.sql.gz

Para restaurar la base de datos 7 a algún punto en el tiempo se requeriría una revisión a través de los archivos FULL y DIFF, y la aplicación manual de ese sql.

¿Cómo debo proceder para poder recuperar uno de los volcados DIFF anteriores en la base de datos maestra?

¿Necesito hacer una copia de seguridad en archivos de bases de datos individuales, es decir

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

más bien que..

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

Si busco archivos mysqldump por separado, ¿qué sucede con el registro binario de datos maestros, y debería incluso configurar --master-data para los volcados de recuperación del servidor maestro?

Tom H
fuente

Respuestas:

7

Si toda su base de datos usa solo InnoDB, tengo buenas noticias.

Debería volcar toda la base de datos en paralelo desde un esclavo.

De hecho, puede forzar todas las bases de datos al mismo punto en el tiempo.

Lo primero que debe recordar acerca de un Esclavo es que no es necesario tener habilitado el registro binario si no es un Maestro para otros Esclavos.

No puede usar la --master-dataopción para volcados paralelos porque cada volcado tendrá una posición diferente escrita en la línea 22 de cada archivo de volcado. Es mejor registrar el último archivo de registro del Maestro y colocar el Esclavo ejecutado usando SHOW SLAVE STATUS\G. De esa manera, todas las bases de datos tienen la misma posición en un punto en el tiempo.

Puede recopilar todas las bases de datos y ejecutar el volcado paralelo de toda la base de datos.

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

Si simplemente hay demasiadas bases de datos, vuélvalas 10 o 20 a la vez de la siguiente manera:

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

Si necesita recuperar una sola tabla, puede volcar en paralelo las tablas 20 a la vez en orden de tamaño.

Prueba esto:

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

Ahora que tiene scripts para volcar bases de datos o tablas individuales, puede cargar esos datos a su discreción. Si necesita ejecutar SQL desde los registros binarios en el maestro, puede usarlo mysqlbinlogy asignarle la posición de fecha y hora y enviar el SQL a otros archivos de texto. Solo tiene que realizar la diligencia debida para encontrar la cantidad de datos que necesita de cualquier marca de tiempo que tengan los registros bnary. Solo recuerde que la marca de tiempo de cada registro binario en el sistema operativo representa la última vez que se escribió.

RolandoMySQLDBA
fuente
respuestas brillantes gracias. Creo que tener un esclavo de solo lectura en xfs me da muchas opciones, y sus scripts realmente han ayudado.
Tom H
en el escenario donde necesito recuperar una tabla masiva para el maestro desde una copia de seguridad del esclavo. Solo tengo que reconstruir la tabla en el maestro y hacer que todos los cambios se repliquen en el esclavo, incluso si son 20 GB de datos. ¿Sería el proceso 1) deshabilitar las teclas, 2) soltar la tabla en el maestro y el esclavo 3) restaurar la tabla en el maestro 4) habilitar las teclas --- y hacer que el maestro replique todos los 20 GB al esclavo?
Tom H
Si estas bases de datos NO son innodb, ¿puedo volcarlas en paralelo?
Tom H
Sí, si 1) programa el tiempo de inactividad, 2) ejecuta service mysql restart --skip-networking, 3) realiza el volcado paralelo, 4) ejecuta service mysql restart. Luego vuelva a cargar las tablas que necesita.
RolandoMySQLDBA
presumiblemente, si el propósito del reinicio era evitar que las conexiones de red se escribieran en la base de datos, entonces podría lograr el mismo efecto usando iptables i.e. iptables -I INPUT -p tcp --dport 3306 -j DROPeth0 y lo
Tom H