MySQL error 1025: explicación y solución

Este post es una traducción al castellano y una ampliación del post MySQL’s ERROR 1025 explained.
En versiones de MySQL superiores o iguales a la 5.5.* el motor de InnoDB ha sido cambiado totalmente y con ello la forma de tratar las claves externas, con ello aparecen nuevos errores como el que vamos a tratar de solucionar hoy:
MySQL Error Number 1025
Error on rename of ‘tabla temporal’ to ‘tabla real’ (errno: 150)

Este error puede aparecer al intentar cambiar el nombre de la columna, o el tipo de datos o su valor por defecto, en fin, cualquier modificación que afecte a una columna de la tabla que sea una foreign key (clave extranjera). O sea MySQL emite un mensaje de error crítico, error on rename (error en cambiar el nombre), cuando se intenta modificar una tabla de tal manera que se tenga que romper una restricción de clave externa.

Explicación del error 1025 de MySQL

Para comprender la solución primero debemos entender el origen de este error y con ello el funcionamiento de MySQL. Este error se produce porque ALTER TABLE realmente funciona haciendo una copia de la tabla, luego, cambiar el nombre de la tabla antigua y la saca de en medio y mueve la tabla nueva en su lugar. EL error 1025 es uno de los mensajes de error menos significativo en MySQL.
Hay un poco más de información al ejecutar la consulta SHOW INNODB STATUS. Existe otra herramienta de monitorado llamada innotop que también puede ayudar a detectar el origen del error.

Solución al error 1025 de MySQL

La solución pasa por eliminar la clave externa primero, luego el índice. El orden sería el siguiente:
  1. eliminar la clave externa
  2. eliminar el índice que se genera al crear la clave externa
  3. modificar la columna con los cambios deseados
  4. volver a crear la clave externa (automáticamente se crea el índice)
Yo soy de la vieja escuela y utilizo aún en MySQL Query Browser pero todos estos pasos se pueden realizar con consultas SQL, la solución más completa con SQL sería la siguiente:
SET FOREIGN_KEY_CHECKS = 0;
ALTER TABLE tableX DROP FOREIGN KEY fkId;
ALTER TABLE tableX DROP INDEX fkId;
ALTER TABLE tableX CHANGE COLUMN changes
ALTER TABLE tableX ADD CONSTRAINT fkId FOREIGN KEY fkId (column) REFERENCES
SET FOREIGN_KEY_CHECKS = 1;

Los pasos 1 y 6 son opcionales, son más bien por si falla sin ellos.
Importante: este error solo afecta a las claves externas cualquier otro tipo de índices es automáticamente borrado y restaurado (en caso de hacerlo desde MySQL Query Browser) en mi caso esta columna también era única y el índice se borró y creó de manera automática.
Con el Query Browser es todo más sencillo, es eliminar la clave externa y luego el índice. ¿Os funciona?

Comentarios

Anónimo ha dicho que…
funciono a la perfección.

Gracias!
Anónimo ha dicho que…
ES posible que haya que realizar algún paso adicional, dependiendo del cambio que se realice en la columna. Si no deja crear la constraint, aquí explican los posibles motivos:

http://verysimple.com/2006/10/22/mysql-error-number-1005-cant-create-table-mydbsql-328_45frm-errno-150/

(Por ejemplo, yo cambié la collation de una columna y tuve que cambiar también la de la clave foránea antes de crear la clave)
Unknown ha dicho que…
Muchas gracias por la explicación. Llegué al límite de registros en una tabla y no me dejaba cambiar el tipo de columna por culpa de las Foreign Keys.

Siguiendo este procedimiento conseguí ampliar la columna.

Un saludo.