Cómo verificar y optimizar bases de datos MySQL desde SSH con mysqlcheck

Mantenimiento de bases de datos MySQL desde la línea de comandos: check, analyze y optimize

Cuando administras un servidor con cPanel/WHM que aloja decenas o cientos de bases de datos MySQL, eventualmente te encontrarás con situaciones donde necesitas verificar la integridad de las tablas o mejorar el rendimiento de las consultas. Esto es especialmente común después de eventos como migraciones, restauraciones de backup, upgrades o downgrades de versión de MySQL.

La herramienta mysqlcheck te permite realizar estas tareas sobre todas las bases de datos del servidor de una sola vez, sin necesidad de entrar a cada cuenta cPanel por separado. En este artículo aprenderás a usarla correctamente y, sobre todo, a saber cuándo no usarla.

Verificar la integridad de todas las bases de datos

El comando --check realiza una verificación de solo lectura sobre cada tabla, comprobando que no haya corrupción estructural. No modifica ningún dato, por lo que es completamente seguro de ejecutar en producción.

  1. mysqlcheck --all-databases --check

La salida mostrará cada tabla seguida de OK si todo está en orden. Si alguna tabla presenta problemas, verás mensajes como Table is marked as crashed o errores específicos que requerirán intervención.

Cuándo usarlo

  1. Después de un reinicio inesperado del servidor o una caída abrupta del servicio MySQL.
  2. Tras detectar errores extraños en los logs de aplicaciones (errores 10341146, mensajes de tablas dañadas).
  3. Como auditoría anual durante una ventana de mantenimiento.
  4. Si sospechas que un cliente reporta corrupción tras un evento específico. En tal caso, es mejor una verificación a la base de datos especifica en lugar de a todo el servidor.

Recalcular estadísticas de índices (cardinalidad)

El comando --analyze regenera las estadísticas que utiliza el optimizador de consultas de MySQL para decidir qué índices usar y en qué orden. Cuando estas estadísticas están desactualizadas, el optimizador puede elegir planes de ejecución subóptimos, causando lentitud notable en aplicaciones como WordPress, WooCommerce, Moodle, etc.

  1. mysqlcheck --all-databases --analyze

Puedes usar el parámetro --skip-write-binlog evita que estas operaciones se escriban en el binlog (útil si tienes replicación o simplemente para no inflarlo innecesariamente).

A diferencia del --check, el --analyze es muy rápido incluso en servidores con cientos de bases de datos, ya que solo toma una muestra de páginas por tabla para estimar la cardinalidad de los índices.

Cuándo usarlo

  1. Después de un dump/reimport de bases de datos (caso típico tras un upgrade o downgrade de MySQL).
  2. Después de restaurar backups grandes con JetBackup u otras herramientas.
  3. Tras una migración de servidor.
  4. Cuando un cliente reporta lentitud súbita en consultas que antes funcionaban bien.
  5. Después de purgas masivas de datos en tablas grandes.

¿Y qué hay del comando --optimize?

Aquí es donde la mayoría de tutoriales en internet dan malos consejos. Existe la creencia popular de que correr mysqlcheck --all-databases --optimize periódicamente es "buena práctica", pero en la realidad, rara vez es necesario y puede ser contraproducente.

Por qué no se recomienda como mantenimiento general

  1. En InnoDB (el motor que usan más del 99% de las tablas modernas), OPTIMIZE TABLE se traduce internamente en una reconstrucción completa de la tabla. Esto requiere espacio temporal en disco equivalente al tamaño de la tabla.
  2. Bloquea escrituras durante el proceso, lo que afecta a sitios activos.
  3. Genera I/O intenso que puede degradar el rendimiento de otros clientes en el servidor.
  4. Si el disco tiene poco espacio libre, puede llenar el filesystem y dejar el servidor caído.
  5. En la mayoría de tablas no aporta ningún beneficio real porque no presentan fragmentación significativa.

Cuándo sí tiene sentido (y cómo hacerlo correctamente)

OPTIMIZE solo es útil cuando una tabla específica tiene fragmentación significativa, es decir, cuando ha tenido borrados masivos y el espacio liberado no se ha devuelto al sistema operativo. Casos típicos: tablas de logs como wp_wfHitswp_loginizer_logswp_actionscheduler_logs que crecieron a varios GB y luego fueron purgadas.

Paso 1: Identificar tablas con fragmentación real

Ejecuta esta consulta para detectar candidatas legítimas a OPTIMIZE:

  1. mysql -e "
  2. SELECT 
  3.   CONCAT(table_schema,'.',table_name) AS tabla,
  4.   ROUND(data_length/1024/1024, 2) AS data_mb,
  5.   ROUND(data_free/1024/1024, 2) AS free_mb,
  6.   ROUND(data_free/data_length*100, 2) AS pct_free
  7. FROM information_schema.TABLES
  8. WHERE engine='InnoDB' 
  9.   AND data_length > 100*1024*1024
  10.   AND data_free/data_length > 0.3
  11. ORDER BY data_free DESC;"

Solo las tablas que aparezcan en este listado (con más de 100MB de datos y más del 30% de espacio libre interno) son candidatas reales.

Paso 2: Optimizar selectivamente

En lugar de correr el OPTIMIZE sobre todas las bases de datos, hazlo únicamente sobre las tablas detectadas. La forma más segura y recomendada para usuarios finales es hacerlo desde phpMyAdmin dentro de cPanel:

  1. Ingresa a cPanel y abre phpMyAdmin.
  2. Selecciona la base de datos del lado izquierdo.
  3. Marca las tablas que deseas optimizar (o "Marcar todas" si aplica).
  4. En el menú desplegable inferior "Para los elementos seleccionados", elige Optimizar tabla.
  5. Espera a que termine el proceso. Verás un mensaje confirmando la operación.

Este método es preferible porque:

  1. Permite operar sobre una sola base de datos sin afectar al resto del servidor.
  2. Da control granular: puedes elegir solo las tablas problemáticas.
  3. Es accesible para clientes que no tienen acceso SSH.
  4. Reduce el riesgo de bloquear masivamente el servidor.

Comandos útiles:

1. Todas las bases de datos del servidor:

  1. mysqlcheck --all-databases --analyze

2. Una base de datos específica (todas sus tablas):

  1. mysqlcheck --analyze nombre_de_la_base

3. Una tabla específica dentro de una base:

  1. mysqlcheck --analyze nombre_de_la_base nombre_de_la_tabla

4. Múltiples tablas específicas dentro de la misma base:

  1. mysqlcheck --analyze nombre_de_la_base tabla1 tabla2 tabla3

5. Múltiples bases de datos (con el flag --databases):

  1. mysqlcheck --analyze --databases base1 base2 base3

Nota el detalle del último caso: cuando quieres operar sobre varias bases, necesitas el flag --databases para que mysqlcheck entienda que todos los argumentos son nombres de bases y no base tabla1 tabla2. Sin ese flag, interpretaría el primer argumento como base y los demás como tablas.