Recrear base de datos MySQL a partir de archivos FRM e IBD
Tiempo total: 10 días con 22:41:39 hrs
El siguiente script sirve para restaurar una base de datos utilizando los archivos .frm y .ibd ubicados en la carpte /var/lib/mysql/mibasededatos.
Paso 1 – Instalar el servidor de base de datos
sudo apt-get install -y mysql-server
Paso 2 – Instalar el paquete “mysql-utilities”
Es necesario instalar este paquete para tener acceso al programa “mysqlfrm”.
sudo apt-get install -y mysql-utilities
Paso 3 – Crear script automatizado
El siguiente script está divido en dos partes:
- Extra el código SQL de creación de la tabla y crea la tabla en la base de datos indicada.
- Reestablece el archivo .ibd en la tabla creada (restaura los datos).
El código es el siguiente:
pw=$1
db=$2
dbfiles=$3
sqlfiles="sql/"
mysql -B -N -e "ALTER USER 'root'@'localhost' IDENTIFIED WITH mysql_native_password BY '${pw}';"
mkdir -p $sqlfiles
mysql -u root -p${pw} -B -N -e "DROP DATABASE $db;"
mysql -u root -p${pw} -B -N -e "CREATE DATABASE $db;"
echo "Script to create empty tables"
frms=$(ls $dbfiles | grep .frm)
contador=1
for frm in $frms
do
table=$(awk -F'.frm' '{ for( i=1; i<NF; i++ ) print $i }' <<< $frm)
echo $contador" table: "$table
contador=$(expr $contador + 1)
echo $contador". step 1"
mysqlfrm --server=root:${pw}@localhost $dbfiles"/"$frm --port=$(expr $contador + 3306) --user=root > $sqlfiles$frm".sql"
sed -i "s|\`$db\`.||g" $sqlfiles$frm".sql"
sed -i 's|WARNING: Using a password on the command line interface can be insecure.||g' $sqlfiles$frm".sql"
sed -i "s|DEFAULT '0000-00-00 00:00:00'||g" $sqlfiles$frm".sql"
sed -i -e '/^[ \t]*#/d' $sqlfiles$frm".sql"
echo "File created: "$sqlfiles$frm".sql"
sql=$(cat $sqlfiles$frm".sql")
echo $contador". step 2"
mysql -u root -p${pw} $db < $sqlfiles$frm".sql"
done
echo "Please wait 60 seconds"
sleep 60
echo "Script to restore IDB files"
contador=1
for frm in $frms
do
table=$(awk -F'.frm' '{ for( i=1; i<NF; i++ ) print $i }' <<< $frm)
echo $contador" table: "$table
contador=$(expr $contador + 1)
echo $contador". step 1"
echo "ALTER TABLE $table DISCARD TABLESPACE;" | mysql -u root -p${pw} $db
echo $contador". step 2"
ibdfile="/var/lib/mysql/"$db"/"$table".ibd"
rm [ -f $ibdfile] && rm $ibdfile
cp $dbfiles"/"$table".ibd" $ibdfile
chown mysql:mysql $ibdfile
echo $contador". step 3"
echo "ALTER TABLE $table IMPORT TABLESPACE;" | mysql -u root -p${pw} $db
done
mysqldump -u root -p${pw} ${db} > /${db}.sql
Las variables que necesita son las siguientes:
pw=$1
db=$2
dbfiles=$3
sqlfiles="sql/"
pw es la contraseña root de la base de datos. Si tu base de datos ya tiene una contraseña root, entonces es necesario eliminar del código la línea 6:
mysql -B -N -e "ALTER USER 'root'@'localhost' IDENTIFIED WITH mysql_native_password BY '${pw}';"
db es el nuevo nombre de la base de datos a restaurar, puede ser el mismo de la anterior o un nombre nuevo.
dbfiles es la carpeta de datos que contiene los archivos de datos .frm e .ibd de la base de datos que quieres restaurar.
El valor de sqlfiles será únicamente la ruta en donde se estarán creando los SQL de cada tabla, puede dejarse con el valor por defecto.
Paso 4 – Ejecutar el script automatizado
Al script automatizado asígnale el nombre de recover.sh, y ejecuta los siguientes comandos. A continuación asumiremos que la base de datos no tiene contraseña root y le asignaremos el valor “rootpw”, la base de datos que queremos crear se llamará “mibasededatos” y la carpeta en donde están los archivos frm e ibd es “/backup/mibasededatos”:
chmod +x recover.sh
./recover.sh 'rootpw' 'mibasededatos' '/backup/mibasededatos/'
Problemas de compatibilidad con el script
El paquete “mysql-utilities” posiblemente no esté disponible para tu distribución o versión Linux, por esta razón no podrás utilizar el programa “mysqlfrm”. Por este motivo, a continuación, está el código Dockerfile para que puedas crear una imagen con el único objetivo de extraer un backup SQL de tus archivos .frm e .ibd. Recuerda modificar el nombre de la base de datos (la contraseña root puede continuar con el valor por defecto).
FROM ubuntu:bionic
ENV DB_PW="root"
ENV DB_NAME="mibasededatos"
COPY mibasededatos.zip /mibasededatos.zip
COPY recover.sh /recover.sh
RUN apt-get update && \
apt-get install -y \
mysql-server \
mysql-utilities \
unzip && \
service mysql start && \
unzip /${DB_NAME}.zip && \
echo "/bin/bash /recover.sh ${DB_PW} ${DB_NAME} '/${DB_NAME}' \r\n" > exec.sh && \
echo "wait -n" >> exec.sh && \
echo "exit $?" >> exec.sh && \
chmod +x /exec.sh && \
chmod +x /recover.sh
CMD ["mysqld"]
Compilar la imagen para recuperar la base de datos
La carpeta que contiene el archivo Dockerfile necesita tener el script recuperar.sh y la carpeta que contiene los archivos .frm e ibd en formato zip.
mkdir recuperar
mv recuperar.sh recuperar/
mv /backup/mibasededatos recuperar/mibasededatos
cd recuperar
zip mibasededatos.zip mibasededatos -r
Una vez hemos creado el archivo zip de la base de datos y movido el archivo recuperar.sh, es posible crear la imagen, crear un contenedor con esa imagen y ejecutar el comando “/bin/bash /exec.sh”:
docker build ./ -t mysql_recover
docker run -dt --name=recover mysql_recover
docker container exec recover /bin/bash /exec.sh
El script tardará bastante tiempo, dependiendo de la cantidad de tablas y datos de la base de datos. Después de finalizado el script, puedes extraer el backup en formato SQL con el siguiente comando:
docker container cp recover:mibasededatos.sql mibasededatos.sql
Por último, elimina el contenedor y la imagen creada con los siguientes comandos:
docker container stop recover
docker container rm recover
docker image rem mysql_recover