Cómo Optimizar MySQL my.cnf en VPS Pequeña (1-2 GB RAM) sin Caídas

Aprende a optimizar MySQL my.cnf en VPS pequeña: ajustar InnoDB buffer pool, desactivar performance_schema y reducir RAM sin perder throughput.

Una VPS de 1 o 2 GB de RAM es el punto donde MySQL con valores por defecto empieza a doler. El proceso mysqld ocupa ~450 MB en el arranque, tu aplicación PHP/Node queda apretada, el kernel empieza a matar procesos por OOM y el swap entra en acción destruyendo el I/O. El problema raramente es MySQL en sí — es el my.cnf por defecto, calibrado para un servidor genérico de 8 GB.

Este tutorial cubre los ajustes de my.cnf que realmente importan en una VPS pequeña: dimensionar innodb_buffer_pool_size para la realidad de la máquina, desactivar performance_schema cuando tiene sentido, controlar conexiones y log binario, y validar todo con comandos que ejecutas antes y después. La persona destinataria es un developer que levantó MySQL 8 o MariaDB en un droplet de 1-2 GB, vio al mysqld consumir 40% de la RAM y quiere reducir sin perder rendimiento.

Tiempo de ejecución: 20-30 minutos incluyendo respaldo del my.cnf original, edición, reinicio y medición. Los ajustes valen para MySQL 8.0+ y MariaDB 10.6+ en Ubuntu 22.04/24.04 LTS y Debian 12.

Requisitos previos

Lo que necesitas antes de empezar

VPS Linux (Ubuntu 22.04/24.04 LTS o Debian 12) con 1 o 2 GB de RAM, MySQL 8.0+ o MariaDB 10.6+ instalado y en ejecución, acceso sudo y credenciales del root de MySQL. Haz un respaldo de la base antes — mysqldump --single-transaction --all-databases > backup.sql — porque un reinicio con un my.cnf roto puede impedir que el servicio levante.

Confirma lo que tienes hoy antes de tocar cualquier línea:

RAM total free -m
RAM mysqld ps -o rss= -p $(pidof mysqld)
Versión MySQL mysql --version
Ruta config /etc/mysql/mysql.conf.d/mysqld.cnf

En MariaDB, el archivo principal es /etc/mysql/mariadb.conf.d/50-server.cnf. En ambos, la regla es la misma: no edites /etc/mysql/my.cnf directamente — solo hace !includedir de los archivos en las carpetas mysql.conf.d/ o mariadb.conf.d/.

Diagnóstico del consumo actual

Antes de recortar, mide. Sin línea base, no sabes si el ajuste mejoró.

01

Mira el RSS actual de mysqld y cuánto representa de la RAM:

ps -o pid,rss,cmd -p $(pidof mysqld)
free -m

El valor de rss está en KB. Divide por 1024 para tener MB. En VPS de 1 GB con MySQL 8 por defecto, espera ver entre 380 y 500 MB — muy por encima de lo necesario para la carga real de un sitio pequeño.

02

Mira el uso real del InnoDB buffer pool — si el pool por defecto de 128 MB sobra o falta:

mysql -u root -p -e "SHOW GLOBAL STATUS LIKE 'Innodb_buffer_pool_pages%';"

Qué interpretar:

  • pages_total = tamaño del pool en páginas de 16 KB
  • pages_free cerca de cero = pool lleno, MySQL está reciclando páginas
  • pages_data / pages_total = cuánto está en uso útil

Si pages_free está alto (>30% del total) y el servidor lleva días de uptime, puedes reducir el pool sin perjuicio. Si está cerca de cero e Innodb_buffer_pool_reads (no read_requests) crece rápido, el pool está infradimensionado.

03

Revisa performance_schema — solo él consume 70-100 MB:

mysql -u root -p -e "SELECT SUM(MEMORY_USED)/1024/1024 AS mb FROM sys.x\$memory_global_by_current_bytes;"

En VPS de 1 GB sin una herramienta de profiling externa leyéndolo, es el primer candidato a desactivar.

Editando el my.cnf

Crea un archivo propio de override en lugar de tocar el mysqld.cnf por defecto — así, las actualizaciones del paquete no sobrescriben tus ajustes.

01

Crea el archivo de override:

sudo nano /etc/mysql/mysql.conf.d/99-hostini-tuning.cnf

En MariaDB: /etc/mysql/mariadb.conf.d/99-hostini-tuning.cnf. El número 99 garantiza que este archivo se lee al final — sobrescribe cualquier valor por defecto.

02

Pega esta configuración base para VPS de 1 GB de RAM:

[mysqld]
# InnoDB — corazón de MySQL
innodb_buffer_pool_size = 256M
innodb_buffer_pool_instances = 1
innodb_log_buffer_size = 8M
innodb_flush_method = O_DIRECT
innodb_flush_log_at_trx_commit = 2

# Conexiones — una VPS pequeña no aguanta 150
max_connections = 50
thread_cache_size = 8
table_open_cache = 200
table_definition_cache = 400

# Performance schema — desactivado en 1 GB
performance_schema = OFF

# Binary log — desactivado si NO usas replicación
disable_log_bin
# Para MariaDB usa: skip-log-bin

# Logs lentos para diagnóstico
slow_query_log = 1
slow_query_log_file = /var/log/mysql/slow.log
long_query_time = 2

# Temporales — en RAM hasta este límite
tmp_table_size = 16M
max_heap_table_size = 16M

# Sort/join buffers — por conexión, cuidado con max_connections
sort_buffer_size = 256K
join_buffer_size = 256K
read_buffer_size = 128K
read_rnd_buffer_size = 256K

Para VPS de 2 GB, ajusta solo estas líneas:

innodb_buffer_pool_size = 512M
max_connections = 100
performance_schema = ON
performance-schema-instrument='memory/%=COUNTED'
Cuidado con los buffers por conexión

sort_buffer_size y join_buffer_size se asignan POR CONEXIÓN ACTIVA, no globalmente. Subir cada uno a 4 MB con 100 conexiones = 400 MB potenciales solo en esos buffers. Los valores bajos del snippet (256K) son intencionales — una query lenta en VPS pequeña se resuelve con un índice, no con un buffer mayor.

03

Guarda (Ctrl+O, Enter, Ctrl+X) y valida la sintaxis antes del reinicio:

sudo mysqld --validate-config

Si aparece cualquier error, el servicio no levantará después del reinicio. Corrige antes de continuar. Salida esperada: ninguna línea (el silencio es éxito).

04

Reinicia MySQL y revisa el estado:

sudo systemctl restart mysql
sudo systemctl status mysql --no-pager

En MariaDB: sudo systemctl restart mariadb. Si el estado muestra active (running), sigues adelante. Si falló, lee el motivo en sudo journalctl -u mysql -n 50 — casi siempre es un typo en el .cnf.

Verificación

Confirma que los ajustes aplicaron y que apareció el ahorro de RAM.

01

Confirma los valores que entraron en vigor:

mysql -u root -p -e "SHOW VARIABLES WHERE Variable_name IN ('innodb_buffer_pool_size', 'max_connections', 'performance_schema', 'log_bin', 'tmp_table_size');"

Los valores deben coincidir con lo que pusiste en 99-hostini-tuning.cnf. Si alguno muestra el default antiguo, el archivo no se está leyendo — verifica la ruta y los permisos (debe ser 644 root:root).

02

Mide el consumo de RAM nuevamente:

ps -o pid,rss,cmd -p $(pidof mysqld)
free -m

Expectativa post-ajuste en VPS de 1 GB: mysqld en ~280-340 MB (caída de ~30%). En 2 GB con performance_schema activado: ~500-580 MB. Espera unos minutos con tráfico real antes de la medición final — el pool se calienta y se estabiliza.

03

Ejecuta SHOW STATUS después de 1-2 horas de uso real y confirma que el buffer pool no está ahogándose:

mysql -u root -p -e "SHOW GLOBAL STATUS LIKE 'Innodb_buffer_pool_%';"

Señales de salud: pages_free > 5% del pages_total, reads creciendo despacio comparado con read_requests (ratio de hit > 99%). Si reads explota, sube el buffer pool en 64 MB y vuelve a probar.

Resolución de problemas

MySQL no levanta tras el reinicio

Revisa el log del journal e identifica la línea exacta que rompió:

sudo journalctl -u mysql -n 80 --no-pager

Causas comunes: innodb_buffer_pool_size mayor que la RAM total disponible, O_DIRECT en un filesystem que no lo soporta (raro en ext4/xfs), opción deprecada en MySQL 8 (query_cache_size fue eliminado). Revierte tu 99-hostini-tuning.cnf a la base mínima (solo innodb_buffer_pool_size) y agrega línea por línea.

”Out of memory” en la aplicación tras el ajuste

Redujiste la RAM de MySQL pero la app creció para llenarla. Ejecuta free -m durante carga real y mira si available cae por debajo de 100 MB. Si es así, considera un swappiness más bajo (sudo sysctl vm.swappiness=10) y activa un archivo de swap de 1 GB como red de protección — no es solución de producción, pero evita el OOM kill mientras dimensionas mejor.

Queries que antes eran rápidas se volvieron lentas

Síntoma típico de buffer pool demasiado pequeño — antes la tabla cabía en RAM, ahora no. Revisa Innodb_buffer_pool_reads (no read_requests) en SHOW GLOBAL STATUS antes y después. Si subió drásticamente, aumenta innodb_buffer_pool_size en 64 MB y mide de nuevo. Solución estructural: agregar un índice en la query, no inflar el pool.

Próximos pasos

Con el my.cnf ajustado, vale la pena consolidar la operación:

  • Configura rotación de logs lentos (slow.log crece rápido) vía logrotate en /etc/logrotate.d/mysql-server
  • Agenda mysqldump --single-transaction diario con cron y envíalo a almacenamiento externo (rclone + S3 o Backblaze B2)
  • En producción con replicación o point-in-time recovery, mantén log_bin activado y ajusta expire_logs_days = 7 para controlar el disco
  • Considera subir a una VPS con más RAM si el pool de 256 MB no da abasto — en general, el salto a 4 GB elimina el ajuste fino y te libera para enfocarte en el producto

Una VPS Hostini ya viene con SSD NVMe y un kernel ajustado para workloads de base de datos — O_DIRECT funciona sin fallback silencioso y el I/O predecible reduce la necesidad de un buffer pool gigante para compensar la latencia de un disco lento.

Preguntas frecuentes

¿Cuánta RAM consume MySQL 8 por defecto sin ajustes?

En una instalación estándar de MySQL 8.0 en Ubuntu/Debian, el proceso mysqld ocupa entre 380 y 500 MB de RSS ya en el arranque, sin ninguna conexión activa. Esto proviene principalmente de innodb_buffer_pool_size (128 MB), performance_schema (~80 MB) y tablas mysql.* del sistema. En VPS de 1 GB, esto ya consume ~40% de la RAM antes de cualquier query.

¿Puedo desactivar performance_schema sin romper nada?

Sí, con salvedades. El performance_schema alimenta las vistas sys.* y herramientas como percona-toolkit pt-query-digest. Desactivarlo ahorra 70-100 MB de RAM pero pierdes visibilidad fina de queries lentas. Recomendado en VPS de 1 GB; en 2 GB o más, déjalo activado y ajusta solo los consumers vía setup_consumers.

¿Cuál es el valor ideal para innodb_buffer_pool_size en VPS pequeña?

La regla de 70-80% de la RAM física solo aplica en servidores dedicados a MySQL. En VPS de 1 GB ejecutando MySQL + app web + nginx, deja entre 256 y 384 MB. En VPS de 2 GB, 512 a 768 MB. El resto va para la app, caché del OS y margen contra el OOM killer.

¿Vale la pena desactivar el binary log (log_bin) en VPS pequeña?

Solo desactívalo si NO usas replicación ni point-in-time recovery. El binary log consume IOPS (escritura secuencial) y disco (~10-20% del tráfico de escritura). Sin él, el restore solo vuelve al último mysqldump. Para single-instance con backup diario aceptable, desactivar está bien; para cualquier setup que pueda convertirse en réplica después, mantenlo.

¿Cómo sé si mis ajustes funcionaron?

Ejecuta SHOW GLOBAL STATUS LIKE 'Innodb_buffer_pool_pages%' después de 24h de uso real. Si Innodb_buffer_pool_pages_free queda cerca de cero e Innodb_buffer_pool_reads crece rápido, el pool está pequeño. Combina con free -m para confirmar que el sistema no está en swap. El RSS de mysqld en ps aux debe quedar estable tras el warm-up.

¿Puedo usar MariaDB en lugar de MySQL para ahorrar RAM?

MariaDB 10.6+ tiene un footprint similar al MySQL 8.0 — no hay un ahorro mágico. La diferencia real viene del ajuste del my.cnf, no del fork. MariaDB tiene algunos valores por defecto más conservadores (innodb_buffer_pool_size=128M también), así que los mismos ajustes de este tutorial valen con `[mariadb]` en lugar de `[mysqld]` cuando aplica.

Temas:
Próximos pasos Cloud Ryzen con NVMe y protección DDoS siempre activa.Pon en producción en un VPS Hostini →
¿Te resultó útil este tutorial?
Hablar por WhatsApp