Recuperación de bases de datos MySQL y PostgreSQL corrompidas
Una base de datos corrompida puede ser una de las situaciones más angustiantes para un administrador de sistemas o un desarrollador. A diferencia de un fichero borrado, la corrupción de una base de datos puede ser parcial, silenciosa y difícil de detectar hasta que es demasiado tarde. En este artículo explicamos las causas más comunes, las técnicas de recuperación disponibles y cuándo es necesario recurrir a un servicio profesional.
Causas más comunes de corrupción en bases de datos
La corrupción de una base de datos raramente ocurre sin motivo. Las causas más frecuentes son:
- Corte de tensión durante una escritura: El escenario más clásico. Si el servidor se apaga abruptamente mientras InnoDB está escribiendo en el fichero ibdata1 o en el redo log, el fichero puede quedar en un estado inconsistente.
- Disco lleno (disk full): Cuando el disco se llena al 100% durante una transacción, el motor de base de datos no puede escribir el commit y los ficheros de datos quedan en estado intermedio.
- Kill forzado del proceso (kill -9): Terminar el proceso mysqld o postgres de forma abrupta impide que se complete el proceso de checkpoint y puede dejar el WAL (Write-Ahead Log) inconsistente.
- Fallo de disco subyacente: Si el disco duro o SSD tiene sectores dañados en las zonas donde residen los ficheros de datos, las lecturas devuelven datos incorrectos o errores de I/O.
- Bug en versión de MySQL/PostgreSQL: Aunque poco frecuente, algunas versiones tienen bugs conocidos que causan corrupción bajo condiciones específicas.
- Sistemas de ficheros montados sin journaling: Usar ext2 o FAT32 para bases de datos en producción aumenta enormemente el riesgo de corrupción.
Recuperación de MySQL InnoDB
InnoDB es el motor de almacenamiento predeterminado de MySQL desde la versión 5.5. Sus ficheros de datos son:
- ibdata1: El tablespace del sistema (datos del diccionario, undo logs, en configuraciones antiguas también los datos de las tablas).
- Ficheros .ibd: Con
innodb_file_per_table=ON(predeterminado desde MySQL 5.6), cada tabla tiene su propio fichero .ibd. - ib_logfile0, ib_logfile1: Los redo logs de InnoDB (o
#ib_redo*en MySQL 8.0+).
Los niveles innodb_force_recovery: guía práctica
Cuando MySQL no arranca por corrupción de InnoDB, el primer recurso es el parámetro innodb_force_recovery en el fichero my.cnf:
| Nivel | Qué omite | Cuándo usarlo | Riesgo |
|---|---|---|---|
| 1 (SRV_FORCE_IGNORE_CORRUPT) | Páginas corrompidas (las marca como perdidas) | Primer intento cuando MySQL no arranca | Bajo |
| 2 (SRV_FORCE_NO_BACKGROUND) | Threads de background (purge, etc.) | Si nivel 1 no funciona | Bajo-medio |
| 3 (SRV_FORCE_NO_TRX_UNDO) | Rollback de transacciones al arrancar | Corrupción del undo log | Medio |
| 4 (SRV_FORCE_NO_IBUF_MERGE) | Operaciones de insert buffer | Corrupción del insert buffer | Medio-alto |
| 5 (SRV_FORCE_NO_UNDO_LOG_SCAN) | Undo logs (transacciones incompletas visibles) | Cuando 4 no es suficiente | Alto |
| 6 (SRV_FORCE_NO_LOG_REDO) | Redo logs completamente | Último recurso absoluto | Muy alto — puede agravar la corrupción |
Regla de oro: Siempre sube el nivel de uno en uno. Si consigues arrancar MySQL con un nivel determinado, haz un mysqldump inmediatamente antes de hacer cualquier otra cosa. Con innodb_force_recovery >= 1, MySQL está en modo de solo lectura (en versiones recientes) o no debería hacerse ninguna escritura.
Advertencia importante: Nunca uses nivel 6 si el problema es un disco con sectores dañados, porque MySQL intentará reconstruir datos sobre un soporte defectuoso, empeorando la situación. En ese caso, el primer paso debe ser clonar el disco a nivel de bloque.
Recuperación de tablas MyISAM
El motor MyISAM, aunque obsoleto, sigue usándose en algunas aplicaciones legadas. Sus ficheros son:
- .MYD: Fichero de datos (My Data).
- .MYI: Fichero de índices (My Index).
- .frm: Definición de la estructura de la tabla (en MySQL 5.x).
La herramienta myisamchk puede reparar muchos casos de corrupción de MyISAM: myisamchk -r -v /var/lib/mysql/basedatos/tabla.MYI. En casos graves, si el .MYD está dañado, se puede intentar reconstruir el .MYI desde cero con myisamchk --recover --force.
Recuperación de MariaDB
MariaDB es un fork de MySQL y comparte la mayor parte de la arquitectura de InnoDB, por lo que el proceso de recuperación con innodb_force_recovery es idéntico. Sin embargo, hay diferencias importantes:
- MariaDB 10.x tiene su propia implementación de InnoDB (originalmente llamada XtraDB) con algunos parámetros adicionales de recuperación.
- El fichero de configuración se llama habitualmente
my.cnfo/etc/mysql/mariadb.conf.d/50-server.cnf. - MariaDB tiene el motor Aria (sustituto de MyISAM) con mejor resistencia a corrupción gracias al journaling integrado.
Recuperación de PostgreSQL
PostgreSQL almacena todos sus datos en el directorio PGDATA (típicamente /var/lib/postgresql/[versión]/main/). Los elementos clave son:
- base/: Directorio con un subdirectorio numérico por cada base de datos, que contiene ficheros de segmentos de 1 GB numerados.
- pg_wal/: El Write-Ahead Log (WAL), equivalente al redo log de InnoDB. En versiones anteriores a PostgreSQL 10 se llamaba pg_xlog.
- global/: Tablas de sistema compartidas entre todas las bases de datos.
- pg_control: Fichero de control del clúster; si se corrompe, PostgreSQL no arrancará.
pg_resetwal: el arma de doble filo
Cuando PostgreSQL no puede arrancar por corrupción del WAL o del fichero pg_control, la herramienta pg_resetwal (antes pg_resetxlog) permite resetear el estado del clúster. Sin embargo, es una operación extremadamente peligrosa:
- Al resetear el WAL, se pierden todas las transacciones que no se habían escrito a disco de forma permanente.
- Puede dejar el clúster en un estado inconsistente si había transacciones en vuelo.
- Una vez ejecutado, puede ser imposible determinar qué datos se han perdido sin una auditoría exhaustiva.
- PostgreSQL muestra una advertencia explícita: "If you are not sure, do not proceed."
La alternativa más segura antes de recurrir a pg_resetwal es intentar arrancar PostgreSQL con los parámetros zero_damaged_pages = on y ignore_invalid_pages = on en postgresql.conf.
Comparativa: MySQL vs PostgreSQL vs Microsoft SQL Server
| Motor | Ficheros de datos | Herramienta de recuperación | Dificultad DIY |
|---|---|---|---|
| MySQL InnoDB | ibdata1, .ibd, ib_logfile* | innodb_force_recovery + mysqldump | Media |
| MySQL MyISAM | .MYD, .MYI, .frm | myisamchk | Baja-media |
| MariaDB | Igual que MySQL InnoDB | innodb_force_recovery | Media |
| PostgreSQL | PGDATA/base/, pg_wal/ | pg_resetwal, zero_damaged_pages | Alta |
| Microsoft SQL Server | .mdf (datos), .ldf (log) | DBCC CHECKDB, REPAIR_ALLOW_DATA_LOSS | Media-alta |
En Microsoft SQL Server, el equivalente a innodb_force_recovery es el comando DBCC CHECKDB WITH REPAIR_ALLOW_DATA_LOSS. Al igual que en MySQL, esta operación puede implicar pérdida de datos y debe usarse como último recurso tras agotar las copias de seguridad.
Cuándo las herramientas DIY no son suficientes
Hay situaciones en las que los métodos de recuperación estándar no funcionan y es necesario un servicio profesional:
- Disco subyacente con sectores dañados: Si el disco tiene sectores malos en las zonas de datos de la base de datos, ninguna herramienta de software puede recuperar lo que el disco no puede leer. Es necesario un tratamiento físico del disco antes de intentar la recuperación lógica.
- ibdata1 severamente corrompido: El diccionario de datos de InnoDB está en ibdata1; sin él, los ficheros .ibd individuales son ilegibles sin técnicas forenses especializadas.
- Recuperación de registros individuales: A veces no se necesita recuperar toda la base de datos, sino encontrar y restaurar registros específicos que fueron borrados o modificados por error.
- Corrupción silenciosa no detectada: La corrupción puede existir durante semanas antes de manifestarse, haciendo que las copias de seguridad también estén corrompidas.
- Ficheros .ibd sin ibdata1: En migraciones mal realizadas donde ibdata1 se perdió pero los .ibd están disponibles, es posible recuperar los datos con herramientas especializadas de análisis binario.
Qué hacemos en nuestro servicio de recuperación de bases de datos
- Clonamos el disco a nivel de bloque antes de tocar nada, preservando el estado original.
- Analizamos la estructura de los ficheros de base de datos con herramientas forenses especializadas.
- Intentamos la recuperación en la copia clonada, nunca en el original.
- Reconstruimos las estructuras internas de InnoDB o PostgreSQL según sea necesario.
- Verificamos la integridad de los datos recuperados antes de la entrega.
- Entregamos un volcado SQL verificado y, si es posible, la base de datos restaurada y en funcionamiento.
Precios del servicio de recuperación de bases de datos
| Tipo de recuperación | Descripción | Precio orientativo |
|---|---|---|
| MySQL/MariaDB lógico | innodb_force_recovery, corrupción leve | 200 – 350 € |
| MySQL InnoDB avanzado | ibdata1 corrompido, reconstrucción de diccionario | 350 – 550 € |
| PostgreSQL | Corrupción de pg_wal / pg_control, pg_resetwal | 300 – 500 € |
| Base de datos + disco dañado | Requiere recuperación física del disco previa | 400 – 700 € |
| SQL Server .mdf/.ldf | DBCC CHECKDB, recuperación de fichero MDF | 300 – 600 € |
| Urgente | Prioridad máxima, entrega en 24-48h | +50% sobre tarifa |
Diagnóstico gratuito y sin compromiso. Solo se cobra si se recuperan datos.