Script automático de exportación/importación de bases de datos por tablas + compresión

database plan

Tenia mucho tiempo que no compartía un recurso, y hoy me toco una tarea que pensé iba a tomarme mucho tiempo. El requerimiento era respaldar una base de datos MySQL grande de casi 90GB, y cargarla en un nuevo servidor. El problema es que no deseaban importar todas las tablas en el nuevo servidor, pero si mantener su respaldo.

Ya había escrito antes una una guía de lo básico para exportar e importar bases de datos desde la consola, pero en este caso particular la situación es que son muchas tablas y el requerimiento fue, exportar por tablas para su respaldo e importar las necesarias. Por tal motivo hice un pequeño bash que genera todo el trabajo de forma automática.

Exportando cada tabla en un .sql independiente

Primero que nada, debemos definir las variables que vamos a usar en nuestro script. Lo hice rápido, así que mi solución fue colocar variables seteadas desde el inicio pero si te gusta algo más «personalizado», puedes solicitar al usuario el ingreso de datos.

#!/bin/bash

#
# ESTE SCRIPT EXPORTA LAS TABLAS DE UNA BASE DE DATOS A UN DIRECTORIO
# ESPECIFICO, GENERANDO UN ARCHIVO .sql POR CADA TABLA
#

#
# Variables del Script
#
dbname=nombre_base			# Nombre de la base de datos
dbuser=root				# Usuario de MySQL
dbpass=miclave				# Contraseña de MySQL
dbbackup=/backup/			# Directorio donde se almacenara el respaldo

#
# Solicitamos datos al usuario
#
#echo 'Ingrese el nombre de la base de datos:'
#read dbname

#echo 'Ingrese el usuario de MySQL:'
#read dbuser

#echo 'Ingrese la clave de MySQL:'
#read dbpass

#echo 'Ingrese la ruta de exportacion Ej. /backup/:'
#read dbbackup

Una vez obtenido los datos necesarios para el funcionamiento del script, nos conectamos a MySQL y obtenemos la lista de las tablas de nuestra base de datos ejecutamos el comando show tables;

Posteriormente procedemos a recorrer cada uno de los resultados. Nótese que elimino la primer linea del resultado, ya que no corresponde a un nombre de la tabla.

# Conectamos a MySQL
echo 'Conectando a MySQL...'
tablas=$(mysql -u $dbuser -p$dbpass -e "use $dbname; show tables;")
echo 'Respaldando tablas...'

# Recorremos la tabla
contador=0
for tabla in $tablas; do
  if [[ contador -gt 1 ]] # eliminamos la primer linea
  then
	# realizamos dump a la tabla
	echo "Respaldando tabla $tabla..."
	mysqldump -u $dbuser -p$dbpass $dbname $tabla --skip-add-locks > $dbbackup$tabla.sql
	echo "ok!";
  fi
  ((contador=$contador+1))
done
echo 'Todas las tablas han sido respaldadas.'

Una vez generados todos los archivos .sql de manera separada, tal cual fue mi necesidad, procedemos a comprimir cada uno de ellos en un archivo .zip para reducir su espacio, recordemos que al menos en mi necesidad puntual no usare todas las tablas exportadas, pues simplemente es para generar un respaldo de la data en general.

#!/bin/bash

#
# Comprimimos los archivos .sql generados
#
echo 'Comprimimos archivos...'

# Recorre todos los archivos del directorio y comprimimos
for archivo in $(ls -C1 $dbbackup)
do
  zip $dbbackup$archivo.zip $dbbackup$archivo
done
echo 'Proceso de compresion de archivos .sql, terminado.'

# Empaquetamos todos los .zip en un solo archivo
echo 'Empaquetamos archivos .zip en un solo archivo:'
zip $dbname.zip $dbbackup*.zip
echo "Archivo $dbname.zip generado!"

Tambien podemos generar un solo archivo zip unicamente con el comando  zip $dbname.zip $dbbackup*.sql  con el cual empaquetariamos en un solo archivo .zip todos los .sql, por lo que todo el codigo anterior seria innecesario.

Pero esta no es mi necesidad, por tal motivo empaquete cada archivo .sql por separado, ya que solo usare algunas tablas y prefiero manipularlas en .zip, luego pienso automatizar la descrompresión y la cargar 😉

Para no ocupar espacio de manera innecesaria en el disco, procedemos a eliminar los archivos .zip generados anteriormente por cada una de las tablas.

# Borramos los archivos .zip independientes, para liberar espacio.
rm -Rf $dbbackup*.zip

Puedes también borrar todo lo respaldado en el directorio, si lo deseas, puesto que en el pedazo de código anterior ya se genero el .zip con toda la data. Para esto solo necesitas modificar la linea de código anterior por esta: rm -Rf $dbbackup

El código final

Para el código final he dejado comentado las lineas donde se solicita al usuario la data, puesto que ya la seteo directamente, y adicionalmente he dejado comentado la linea que elimina los archivos .zip generados para que puedas personalizarlo a tu gusto. El código final quedaría así:

#!/bin/bash

#
# ESTE SCRIPT EXPORTA LAS TABLAS DE UNA BASE DE DATOS A UN DIRECTORIO
# ESPECIFICO, GENERANDO UN ARCHIVO .sql POR CADA TABLA
#

#
# Variables del Script
#
dbname=nombre_base			# Nombre de la base de datos
dbuser=root				# Usuario de MySQL
dbpass=miclave				# Contraseña de MySQL
dbbackup=/backup/			# Directorio donde se almacenara el respaldo

#
# Solicitamos datos al usuario
#
#echo 'Ingrese el nombre de la base de datos:'
#read dbname

#echo 'Ingrese el usuario de MySQL:'
#read dbuser

#echo 'Ingrese la clave de MySQL:'
#read dbpass

#echo 'Ingrese la ruta de exportacion Ej. /backup/:'
#read dbbackup

# Conectamos a MySQL
echo 'Conectando a MySQL...'
tablas=$(mysql -u $dbuser -p$dbpass -e "use $dbname; show tables;")
echo 'Respaldando tablas...'

# Recorremos la tabla
contador=0
for tabla in $tablas; do
  if [[ contador -gt 1 ]] # eliminamos la primer linea
  then
	# realizamos dump a la tabla
	echo "Respaldando tabla $tabla..."
	mysqldump -u $dbuser -p$dbpass $dbname $tabla --skip-add-locks > $dbbackup$tabla.sql
	echo "ok!";
  fi
  ((contador=$contador+1))
done
echo 'Todas las tablas han sido respaldadas.'

#
# Comprimimos los archivos .sql generados
#
echo 'Comprimimos archivos...'

# Recorre todos los archivos del directorio y comprimimos
for archivo in $(ls -C1 $dbbackup)
do
  zip $dbbackup$archivo.zip $dbbackup$archivo
done
echo 'Proceso de compresion de archivos .sql, terminado.'

# Empaquetamos todos los .zip en un solo archivo
echo 'Empaquetamos archivos .zip en un solo archivo:'
zip $dbname.zip $dbbackup*.zip
echo "Archivo $dbname.zip generado!"

# Borramos los archivos .zip independientes, para liberar espacio.
# rm -Rf $dbbackup*.zip

echo 'Fin :)'

Recuerda que debes dar permisos de ejecución al script con chmod a+x exportar.sh  y luego lo corres únicamente ejecutando ./exportar.sh

y ahora… ¿Cómo muevo el archivo generado, de gran tamaño, a un nuevo servidor?

Mi hermano me comparte una solución bastante efectiva que es transfiriendo el fichero por ssh con rsync, para lo que basta únicamente usar el siguiente comando:

/usr/bin/rsync -aHAXxvS --numeric-ids --delete --progress -e "ssh -T -o Compression=no -x" /backup/archivo.zip root@192.168.0.0:/ruta/carga/

Simplemente reemplaza /backup/archivo.zip por la ruta y nombre de tu archivo local y reemplaza root@192.168.0.0:/ruta/carga/ por tu user@host y la ruta de destino del fichero.

Una vez exportada la data, con los ejemplos anteriores, queda ya muy fácil importarla.

Espero les haya gustado y les sea de utilidad. Salud!