20 junio, 2025

Cuando usamos un script en Bash para realizar respaldos de todas las bases de datos MySQL (excepto las de sistema), a veces nos encontramos con el mensaje:

mysqldump: Got error: 1049: "Unknown database 'Database'" when selecting the database

Este error se produce porque, al listar las bases con SHOW DATABASES, el primer elemento que aparece es el encabezado Database, y si no lo filtramos correctamente, el bucle de respaldo intentará ejecutar mysqldump Database, provocando el error de “base desconocida”. En este artículo veremos por qué sucede exactamente, y presentaremos dos soluciones sencillas para eliminar esa línea del encabezado y evitar el fallo.


¿Por qué aparece “Database” en la lista de bases?

Supongamos que tenemos un script llamado backupbases.sh con este fragmento:

#!/bin/bash

# Directorio de trabajo
DIRECTORIO=`pwd`

# Fecha de respaldo
DATE=`date +%Y-%m-%d-%H-%M`

### // Respaldando bases de MySQL \\ ###

# Seleccionar las bases a respaldar (todas menos la palabra Database que aparece al listar las bases)
LIST2=$(mysql -e "show databases" -u root --password=password | awk '{print $1}' | grep -vE '^-|^Database |^information_schema')

# Respaldar cada base y ubicar el respaldo en el directorio actual
for e in $LIST2
do
  echo "respaldando $e"
  mysqldump $e -u root --password=password -c > $DIRECTORIO/$e-$DATE.mysql
done

### \\ Respaldando bases de MySQL // ###

Cuando corremos mysql -e "show databases", la salida normal es:

Database
information_schema
mysql
performance_schema
database1
database2
...
  • La primera línea es Database (sin comillas), que actúa como encabezado de columna.
  • Luego vienen todas las bases, incluidas las de sistema como information_schema y performance_schema.

El problema reside en la parte:

… | awk '{print $1}' | grep -vE '^-|^Database |^information_schema'
  • awk '{print $1}' extrae la primera columna de cada línea, por lo que produce: Database information_schema mysql performance_schema database1 database2 ...
  • El patrón ^Database (con un espacio después de “Database”) no coincide con la línea Database (que no tiene un espacio al final). Por tanto, “Database” no se filtra, y queda en la variable $LIST2.
  • Al iterar sobre $LIST2, el bucle ejecuta primero mysqldump Database -u root ..., y MySQL devuelve: Got error: 1049: "Unknown database 'Database'" when selecting the database

Para eliminar este encabezado de manera correcta, podemos usar dos estrategias principales.


Opción 1: usar --skip-column-names al listar bases

MySQL permite omitir la fila de encabezado en la salida de consultas usando la opción --skip-column-names (o su forma corta -N). De este modo, el comando

mysql -u root --password=password --skip-column-names -e "SHOW DATABASES;"

devuelve directamente:

information_schema
mysql
performance_schema
database1
database2
...

sin la línea “Database” al inicio. Luego solo tenemos que filtrar las bases de sistema que no queremos respaldar, por ejemplo:

#!/bin/bash

# Directorio de trabajo
DIRECTORIO="$(pwd)"

# Fecha de respaldo (AAAA-MM-DD-HH-MM)
DATE="$(date +%Y-%m-%d-%H-%M)"

### // Respaldando bases de MySQL \\ ###

# Listar bases (sin cabecera) y excluir sólo information_schema y performance_schema
LIST2=$(
  mysql -u root --password=password \
    --skip-column-names \
    -e "SHOW DATABASES;" \
    | grep -Ev '^(information_schema|performance_schema)$'
)

# Respaldar cada base y guardar el archivo en el directorio actual
for e in $LIST2; do
  echo "respaldando $e"
  mysqldump -u root --password=password -c "$e" \
    > "$DIRECTORIO/$e-$DATE.mysql"
done

### \\ Respaldando bases de MySQL // ###

¿Qué hace este script?

  1. --skip-column-names quita el encabezado “Database”.
  2. grep -Ev '^(information_schema|performance_schema)$' elimina exactamente las dos bases de sistema que no queremos respaldar.
  3. El bucle for e in $LIST2 recorre únicamente los nombres de bases válidos (por ejemplo, mysql, database1, database2, …).
  4. Para cada base, se ejecuta mysqldump y se genera un archivo con nombre <base>-<fecha>.mysql.

Con esto, ya no aparece la línea “Database” en $LIST2, y por ende desaparece el error 1049.


Opción 2: filtrar “Database” exacto con una expresión regular

Si prefieres no usar la opción --skip-column-names, basta con corregir el patrón de grep para que descarte la línea que es exactamente “Database” (sin espacios extra). Para ello, cambiamos el grep -vE '^-|^Database |^information_schema' por:

grep -Ev '^(Database|information_schema|performance_schema)$'

El script completo quedaría así:

#!/bin/bash

# Directorio de trabajo
DIRECTORIO="$(pwd)"

# Fecha de respaldo (AAAA-MM-DD-HH-MM)
DATE="$(date +%Y-%m-%d-%H-%M)"

### // Respaldando bases de MySQL \\ ###

# Listar bases (con encabezado) y filtrar para evitar "Database", "information_schema" y "performance_schema"
LIST2=$(
  mysql -u root --password=password -e "SHOW DATABASES;" \
    | awk '{print $1}' \
    | grep -Ev '^(Database|information_schema|performance_schema)$'
)

# Respaldar cada base válida
for e in $LIST2; do
  echo "respaldando $e"
  mysqldump -u root --password=password -c "$e" \
    > "$DIRECTORIO/$e-$DATE.mysql"
done

### \\ Respaldando bases de MySQL // ###

Por qué funciona

  • awk '{print $1}' sigue sacando la primera columna, incluidos “Database” e “information_schema”.
  • grep -Ev '^(Database|information_schema|performance_schema)$':
    • ^…$ obliga a que coincida toda la línea completa.
    • (Database|information_schema|performance_schema) descarta exactamente esas tres entradas.
  • De esta forma, “Database” ya no está en la lista $LIST2.

Buenas prácticas adicionales

Más allá de eliminar el encabezado “Database”, conviene seguir estos consejos al crear scripts de respaldo:

  1. Separar credenciales
    Evita poner la contraseña en texto claro dentro del script. En su lugar, crea un archivo ~/.my.cnf con contenido similar a: [client] user=root password=TU_CONTRASEÑA Y ajusta el script para usar simplemente mysql y mysqldump sin -u root --password=….
  2. Excluir otras bases de sistema
    Además de information_schema y performance_schema, podrías querer excluir mysql (dependiendo de si quieres respaldar los privilegios) o sys. Ajusta el grep -Ev '…' para incluirlas en caso de no necesitar un backup de esas bases.
  3. Almacenamiento separado por fecha
    En lugar de guardar todos los .mysql en el mismo directorio, podrías crear una subcarpeta con la fecha del día: DIR_RESPALDO="$DIRECTORIO/respaldos/$(date +%Y-%m-%d)" mkdir -p "$DIR_RESPALDO" … > "$DIR_RESPALDO/$e-$DATE.mysql" Así tendrás ordenados los respaldos por día.
  4. Manejo de errores
    Captura el código de salida de mysqldump para detectar fallos y, si uno ocurre, notifica por correo o detén el script: if ! mysqldump -u root --password="$PASSWORD" -c "$e" > "$ARCHIVO"; then echo "Error: no se pudo respaldar $e" >&2 exit 1 fi
  5. Programar con cron
    Para automatizar el respaldo diario, añade una entrada en el crontab del usuario: 0 2 * * * /ruta/a/backupbases.sh >> /ruta/a/log_backupbases.log 2>&1 Esto ejecuta el script cada día a las 2 AM y redirige la salida a un archivo de log.

Conclusión

El error:

mysqldump: Got error: 1049: "Unknown database 'Database'" when selecting the database

se debe a que el encabezado literal Database que MySQL imprime al listar bases no se estaba filtrando correctamente, quedando en la lista de $LIST2. Para evitarlo, puedes:

  1. Opción 1: usar mysql --skip-column-names -e "SHOW DATABASES;" y luego filtrar solo las bases de sistema que no deseas respaldar.
  2. Opción 2: mantener la salida con encabezado y ajustar grep -vE para excluir exactamente la línea Database, junto con information_schema y performance_schema.

Ambas soluciones impiden que el bucle intente respaldar una base llamada “Database” y, por tanto, evitan el error 1049. Elige la que mejor se adapte a tu entorno y, de paso, considera implementar buenas prácticas como separar las credenciales, organizar los backups por carpetas y manejar errores dentro del script. ¡Así tendrás un respaldo confiable y libre de fallos!

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *