Recrear base de datos MySQL a partir de archivos FRM e IBD

Visitas: 182  
Tiempo total: 5 días con 1:21:4 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:

  1. Extra el código SQL de creación de la tabla y crea la tabla en la base de datos indicada.
  2. 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

Para recibir boletines de información, por favor escribe tu correo electrónico:

Por favor ingrese un correo electrónico valido.
Registrado correctamente!