Toda la configuración persistente de MySQL reside en un archivo de texto llamado my.cnf en sistemas Unix/Linux o my.ini en Windows. Este archivo controla desde el puerto en que escucha el servidor hasta el tamaño del buffer pool, pasando por las opciones del cliente de línea de comandos y los parámetros de replicación. Dominar su estructura y entender el orden en que MySQL lee los archivos de configuración te dará un control completo sobre el comportamiento del servidor.

Ubicación del archivo

MySQL busca archivos de configuración en varias ubicaciones predeterminadas, y el orden importa porque los valores que se leen después sobrescriben los anteriores. Puedes ver exactamente qué archivos busca MySQL con:

mysqld --verbose --help 2>/dev/null | grep -A1 "Default options"
Default options are read from the following files in the given order:
/etc/my.cnf /etc/mysql/my.cnf /usr/etc/my.cnf ~/.my.cnf

En distribuciones basadas en Debian, la ubicación principal suele ser /etc/mysql/my.cnf, que a su vez incluye archivos desde /etc/mysql/conf.d/ y /etc/mysql/mysql.conf.d/. En distribuciones basadas en Red Hat, el archivo principal es /etc/my.cnf.

En Windows, MySQL busca en:

C:\Windows\my.ini
C:\Windows\my.cnf
C:\my.ini
C:\my.cnf
C:\Program Files\MySQL\MySQL Server 8.0\my.ini

Para saber exactamente qué archivo está usando tu instancia actual, puedes verificar con qué opciones se inició el proceso:

ps aux | grep mysqld | grep -o '\-\-defaults-file=[^ ]*'

Estructura de secciones

El archivo my.cnf se organiza en secciones delimitadas por encabezados entre corchetes. Cada sección contiene parámetros que aplican a un programa específico de MySQL.

# Configuración global del servidor MySQL
 
[mysqld]
# Opciones para el proceso del servidor
port            = 3306
bind-address    = 0.0.0.0
datadir         = /var/lib/mysql
socket          = /var/lib/mysql/mysql.sock
log-error       = /var/log/mysql/error.log
pid-file        = /var/run/mysqld/mysqld.pid
 
# Almacenamiento InnoDB
innodb_buffer_pool_size = 4G
innodb_log_file_size    = 256M
innodb_flush_log_at_trx_commit = 1
 
# Conexiones
max_connections     = 200
wait_timeout        = 600
interactive_timeout = 600
 
[mysql]
# Opciones para el cliente mysql de línea de comandos
prompt         = "\\u@\\h [\\d]> "
auto-rehash
default-character-set = utf8mb4
 
[client]
# Opciones para TODOS los programas cliente de MySQL
port    = 3306
socket  = /var/lib/mysql/mysql.sock
default-character-set = utf8mb4
 
[mysqldump]
# Opciones para la herramienta de backup mysqldump
quick
max_allowed_packet = 64M
single-transaction

La sección [mysqld] es la más importante porque configura el servidor en sí. La sección [client] afecta a todos los programas cliente que incluyen la librería de MySQL (mysql, mysqldump, mysqladmin, etc.). La sección [mysql] solo afecta al cliente interactivo de línea de comandos.

Parámetros comunes de la sección [mysqld]

Los parámetros del servidor se pueden agrupar por categoría. Estos son los más importantes que todo administrador debe conocer y ajustar:

[mysqld]
# === RED Y CONEXIONES ===
port                = 3306
bind-address        = 0.0.0.0
max_connections     = 200
max_connect_errors  = 100
 
# === MEMORIA E INNODB ===
innodb_buffer_pool_size    = 4G
innodb_buffer_pool_instances = 4
innodb_log_file_size       = 256M
innodb_flush_log_at_trx_commit = 1
 
# === LOGGING ===
log_error           = /var/log/mysql/error.log
slow_query_log      = ON
slow_query_log_file = /var/log/mysql/slow.log
long_query_time     = 2
 
# === CARÁCTER Y COLLATION ===
character-set-server  = utf8mb4
collation-server      = utf8mb4_unicode_ci
 
# === SEGURIDAD ===
local_infile = OFF
sql_mode     = STRICT_TRANS_TABLES,NO_ENGINE_SUBSTITUTION,NO_ZERO_DATE

El parámetro innodb_buffer_pool_size es posiblemente el más impactante para el rendimiento. En un servidor dedicado a MySQL con 16 GB de RAM, un valor razonable sería entre 10 y 12 GB. Si el servidor también ejecuta la aplicación, debes ser más conservador y dejar memoria suficiente para el sistema operativo y la aplicación.

Orden de lectura y reglas de sobrescritura

Cuando MySQL encuentra el mismo parámetro en varios archivos de configuración, el último valor leído gana. El orden de lectura va de lo más general a lo más específico:

1. /etc/my.cnf              (configuración global del sistema)
2. /etc/mysql/my.cnf         (directorio de MySQL)
3. /usr/etc/my.cnf           (instalación personalizada)
4. ~/.my.cnf                 (archivo personal del usuario)
5. --defaults-file=...       (especificado en línea de comandos)

Hay una excepción importante: la opción --defaults-file en la línea de comandos hace que MySQL ignore TODOS los demás archivos de configuración y use únicamente el especificado. En cambio, --defaults-extra-file lee el archivo indicado además de los habituales.

En Debian y Ubuntu, el archivo principal /etc/mysql/my.cnf usa directivas !include y !includedir para organizar la configuración en múltiples archivos:

# /etc/mysql/my.cnf
!includedir /etc/mysql/conf.d/
!includedir /etc/mysql/mysql.conf.d/

Los archivos dentro de estos directorios se leen en orden alfabético. Por eso es común nombrarlos con prefijos numéricos:

/etc/mysql/mysql.conf.d/
├── 10-base.cnf
├── 20-innodb.cnf
├── 30-logging.cnf
└── 40-replication.cnf

Caso práctico: configuración para un servidor de producción

Supongamos un servidor con 32 GB de RAM dedicado a MySQL que maneja una aplicación de gestión empresarial con 50 usuarios concurrentes. Una configuración base razonable sería:

[mysqld]
# Identificación
server-id = 1
 
# Red
port            = 3306
bind-address    = 0.0.0.0
max_connections = 150
max_connect_errors = 1000
 
# InnoDB - Motor de almacenamiento
innodb_buffer_pool_size     = 24G
innodb_buffer_pool_instances = 8
innodb_log_file_size        = 1G
innodb_flush_log_at_trx_commit = 1
innodb_flush_method         = O_DIRECT
innodb_file_per_table       = ON
 
# Buffer pool persistence (calentamiento rápido tras reinicio)
innodb_buffer_pool_dump_at_shutdown = ON
innodb_buffer_pool_load_at_startup  = ON
 
# Temporales y ordenación
tmp_table_size      = 64M
max_heap_table_size = 64M
sort_buffer_size    = 4M
join_buffer_size    = 4M
 
# Logging
log_error                     = /var/log/mysql/error.log
slow_query_log                = ON
slow_query_log_file           = /var/log/mysql/slow.log
long_query_time               = 1
log_queries_not_using_indexes = ON
 
# Seguridad
local_infile = OFF
sql_mode = STRICT_TRANS_TABLES,NO_ENGINE_SUBSTITUTION,NO_ZERO_DATE,NO_ZERO_IN_DATE,ERROR_FOR_DIVISION_BY_ZERO
 
# Character set
character-set-server  = utf8mb4
collation-server      = utf8mb4_unicode_ci
 
[client]
default-character-set = utf8mb4
 
[mysql]
default-character-set = utf8mb4
prompt = "\\u@\\h [\\d]> "

Caso práctico: verificar la configuración activa

Después de modificar my.cnf y reiniciar, siempre debes verificar que los cambios se aplicaron correctamente. La forma más fiable es comparar lo que dice el archivo con lo que reporta el servidor:

SHOW VARIABLES LIKE 'innodb_buffer_pool_size';
Variable_nameValue
innodb_buffer_pool_size25769803776

Ese valor en bytes equivale a 24 GB (24 * 1024^3), confirmando que el parámetro se aplicó.

Para una verificación más completa, puedes exportar todas las variables a un archivo y compararlas:

mysql -u root -p -e "SHOW GLOBAL VARIABLES" > /tmp/variables_actuales.txt

Si sospechas que un parámetro del archivo no se está aplicando, puede ser que otro archivo lo sobrescriba. MySQL 8.0 ofrece una forma de diagnosticar esto:

SELECT VARIABLE_NAME, VARIABLE_VALUE,
       VARIABLE_SOURCE, VARIABLE_PATH
FROM performance_schema.variables_info
WHERE VARIABLE_NAME = 'max_connections';
VARIABLE_NAMEVARIABLE_VALUEVARIABLE_SOURCEVARIABLE_PATH
max_connections200EXPLICIT/etc/mysql/my.cnf

La columna VARIABLE_SOURCE indica de dónde vino el valor (EXPLICIT = archivo de configuración, DYNAMIC = cambiado con SET GLOBAL, COMPILED = valor por defecto compilado).

Es una buena práctica mantener el archivo my.cnf bajo control de versiones (por ejemplo, en un repositorio Git privado) para poder rastrear los cambios y revertir si algo sale mal. En el siguiente artículo exploraremos el directorio de datos, donde MySQL almacena físicamente todas las bases de datos y archivos internos.

Escrito por Eduardo Lázaro