MyISAM
MyISAM fue el motor de almacenamiento predeterminado de MySQL hasta la versión 5.5, cuando fue reemplazado por InnoDB. Durante años fue sinónimo de MySQL y muchos tutoriales antiguos asumen su uso. Sin embargo, en el MySQL moderno, MyISAM es un motor que rara vez deberías elegir conscientemente. Su carencia de transacciones, la ausencia de claves foráneas y el uso de bloqueo a nivel de tabla lo hacen inadecuado para la mayoría de las aplicaciones actuales.
Entender MyISAM sigue siendo importante porque podrías encontrar tablas MyISAM en bases de datos heredadas que necesitas migrar, y porque algunas tablas del sistema de MySQL aún lo utilizan internamente. Conocer sus limitaciones te ayudará a tomar la decisión correcta de migrar a InnoDB cuando sea necesario.
Sintaxis
Para crear una tabla con MyISAM:
CREATE TABLE nombre_tabla (
columna1 tipo_dato,
columna2 tipo_dato
) ENGINE = MyISAM;Comportamiento básico
Cuando creas una tabla MyISAM, MySQL genera tres archivos en el directorio de la base de datos. El archivo .frm contiene la definición de la estructura de la tabla, el archivo .MYD (MYData) almacena los datos y el archivo .MYI (MYIndex) almacena los índices. Esta separación entre datos e índices es una diferencia fundamental con InnoDB, donde ambos se almacenan juntos en el archivo .ibd.
CREATE TABLE log_legacy (
id INT AUTO_INCREMENT PRIMARY KEY,
mensaje VARCHAR(255),
fecha DATETIME
) ENGINE = MyISAM;Después de crear esta tabla, encontrarás los archivos:
log_legacy.frm -- Definición de la tabla
log_legacy.MYD -- Datos
log_legacy.MYI -- Índices
MyISAM no soporta transacciones. Esto significa que no puedes usar START TRANSACTION, COMMIT ni ROLLBACK con tablas MyISAM. Cada sentencia SQL se ejecuta de forma individual y si un INSERT de múltiples filas falla a mitad de camino, las filas ya insertadas permanecen en la tabla sin posibilidad de deshacerlas automáticamente.
-- Esto NO funciona como una transacción en MyISAM
START TRANSACTION;
INSERT INTO log_legacy (mensaje, fecha) VALUES ('acción 1', NOW());
INSERT INTO log_legacy (mensaje, fecha) VALUES ('acción 2', NOW());
ROLLBACK; -- No deshace nada: ambos INSERT persistenCaso práctico: bloqueo a nivel de tabla
La limitación más impactante de MyISAM en aplicaciones de producción es su sistema de bloqueo a nivel de tabla. Cuando una sesión ejecuta una operación de escritura sobre una tabla MyISAM, la tabla completa queda bloqueada para cualquier otra operación de escritura y, dependiendo de la configuración, también para lecturas.
-- Sesión 1: inserta un registro (bloquea toda la tabla)
INSERT INTO log_legacy (mensaje, fecha) VALUES ('proceso largo', NOW());
-- Sesión 2 (simultánea): debe esperar a que termine la sesión 1
INSERT INTO log_legacy (mensaje, fecha) VALUES ('otro proceso', NOW());
-- Esta sentencia queda en espera hasta que se libere el bloqueoEn aplicaciones con alta concurrencia, este comportamiento puede crear cuellos de botella severos. Mientras InnoDB permitiría que ambas sesiones escriban simultáneamente en diferentes registros, MyISAM obliga a que todas las escrituras se serialicen.
Para observar los bloqueos de tabla activos:
SHOW OPEN TABLES WHERE In_use > 0;| Database | Table | In_use | Name_locked |
|---|---|---|---|
| mi_app | log_legacy | 1 | 0 |
Caso práctico: ausencia de claves foráneas
MyISAM no soporta claves foráneas. Si intentas definir una, MySQL la acepta sintácticamente pero la ignora por completo, sin generar un error ni una advertencia.
CREATE TABLE pedidos_legacy (
id INT AUTO_INCREMENT PRIMARY KEY,
cliente_id INT,
total DECIMAL(10,2),
FOREIGN KEY (cliente_id) REFERENCES clientes(id)
) ENGINE = MyISAM;A pesar de la cláusula FOREIGN KEY, MyISAM permite insertar valores en cliente_id que no existen en la tabla clientes:
INSERT INTO pedidos_legacy (cliente_id, total) VALUES (999999, 100.00);
-- Query OK: MyISAM no valida la referenciaEsto significa que la integridad referencial debe ser gestionada enteramente por la aplicación, lo cual es una fuente frecuente de datos inconsistentes en sistemas que usan MyISAM.
Caso práctico: reparación de tablas corruptas
Dado que MyISAM no tiene mecanismos de recuperación automática como InnoDB, es más susceptible a la corrupción de datos después de un fallo del servidor. Cuando una tabla MyISAM se corrompe, las consultas pueden devolver errores o datos incorrectos.
-- Verificar si una tabla está corrupta
CHECK TABLE log_legacy;| Table | Op | Msg_type | Msg_text |
|---|---|---|---|
| mi_app.log_legacy | check | status | OK |
Si la verificación reporta problemas:
-- Intentar reparar la tabla
REPAIR TABLE log_legacy;| Table | Op | Msg_type | Msg_text |
|---|---|---|---|
| mi_app.log_legacy | repair | status | OK |
REPAIR TABLE intenta reconstruir los índices y recuperar los datos que sea posible. Sin embargo, no siempre puede recuperar todos los registros. En caso de corrupción grave, podrías perder datos de forma irrecuperable.
También puedes usar la herramienta de línea de comandos myisamchk para reparar tablas sin tener que iniciar el servidor MySQL:
-- Desde la terminal del sistema operativo (servidor detenido)
-- myisamchk --recover /var/lib/mysql/mi_app/log_legacy.MYICaso práctico: migración de MyISAM a InnoDB
Si encuentras tablas MyISAM en una base de datos existente, la recomendación en la inmensa mayoría de los casos es migrarlas a InnoDB. El proceso es sencillo pero requiere planificación en tablas grandes.
Primero, identifica todas las tablas MyISAM en tu servidor:
SELECT table_schema, table_name, engine, table_rows,
ROUND(data_length / 1024 / 1024, 2) AS data_mb
FROM information_schema.tables
WHERE engine = 'MyISAM'
AND table_schema NOT IN ('mysql', 'information_schema', 'performance_schema', 'sys')
ORDER BY data_length DESC;| table_schema | table_name | engine | table_rows | data_mb |
|---|---|---|---|---|
| tienda | productos_viejo | MyISAM | 45000 | 12.50 |
| tienda | log_accesos | MyISAM | 1200000 | 85.30 |
| blog | comentarios | MyISAM | 8500 | 1.20 |
Para tablas pequeñas, la conversión es rápida y directa:
ALTER TABLE blog.comentarios ENGINE = InnoDB;Para tablas grandes, considera hacerlo durante una ventana de mantenimiento ya que la tabla estará inaccesible durante la conversión:
ALTER TABLE tienda.log_accesos ENGINE = InnoDB;Después de la migración, verifica que todo funciona correctamente:
SELECT table_name, engine FROM information_schema.tables
WHERE table_schema = 'tienda' AND table_name = 'log_accesos';| table_name | engine |
|---|---|
| log_accesos | InnoDB |
Advertencia: En el MySQL moderno, no hay prácticamente ningún caso de uso donde MyISAM sea mejor opción que InnoDB. Incluso para tablas de solo lectura, InnoDB ofrece un rendimiento comparable o superior gracias a su buffer pool. Si encuentras tablas MyISAM en producción, planifica su migración a InnoDB como una prioridad técnica.
Consejo: Antes de migrar de MyISAM a InnoDB, verifica que tu aplicación no dependa de características exclusivas de MyISAM, como los contadores
AUTO_INCREMENTpor grupo en claves compuestas o búsquedasFULLTEXTen versiones de MySQL anteriores a 5.6. En MySQL 8.0, InnoDB soportaFULLTEXTde forma nativa.
En el siguiente artículo aprenderás sobre el motor MEMORY, que almacena las tablas completamente en RAM para un acceso ultrarrápido.
Escrito por Eduardo Lázaro
