No se puede crear la tabla, pero la tabla no existe.

11

Estoy usando estos pasos para crear una tabla my_user, que ya existía pero de alguna manera desapareció de mi base de datos my_db:

mysql> USE my_db;
mysql> DROP TABLE my_user;
mysql> ERROR 1051 (42S02): Unknown table 'my_user'
mysql> CREATE TABLE my_user (id INT AUTO_INCREMENT NOT NULL, username VARCHAR(255), group_id VARCHAR(255) DEFAULT NULL, PRIMARY KEY(id)) DEFAULT CHARACTER SET utf8 COLLATE utf8_unicode_ci ENGINE = InnoDB;
mysql> ERROR 1005 (HY000): Can't create table 'my_db.my_user' (errno: -1)

Intenté # mysqladmin flush-tablesy repetí los pasos anteriores, pero no fue útil. Además, reinició el mysqlservicio, pero no es bueno.

¿Algunas ideas? Google me ha fallado hasta ahora. Gracias.

Información extra:

mysql> SHOW engine innodb STATUS;
------------------------
LATEST FOREIGN KEY ERROR
------------------------
140703 15:15:09 Error in foreign key constraint of table my_db/my_user
there is no index in the table which would contain
the columns as the first columns, or the data types in the
table do not match the ones in the referenced table
or one of the ON ... SET NULL columns is declared NOT NULL. Constraint:
,
  CONSTRAINT "FK_CFBD431E285FAC6D" FOREIGN KEY ("group_id") REFERENCES "my_group" ("id")
sangrado
fuente
1
¿Estás seguro de que no tienes un error tipográfico en alguna parte? Dices que estás creando una tabla my_userpero el error es sobre my_db.user...
mustaccio
@mustaccio, sí cometió un error al acortar el nombre de la tabla a my_user (el original tiene un nombre más largo y confuso). En realidad, el CREATE TABLEcódigo es generado por la biblioteca Doctrine ORM (PHP).
Sangrado el
Entonces, estos no son los nombres reales, solo nos estás
tomando el
Si ha abandonado el registro en el diccionario InnoDB, no le permitirá crear una tabla con el mismo nombre. Parece su caso, pero necesita más investigación. Intente poner my_user.frm y my_user.ibd falsos y suelte la tabla.
akuzminsky
¿El nombre real de la tabla tiene algún carácter extraño (no alfanumérico)? ¿Comienza con un dígito o un personaje extraño?
ypercubeᵀᴹ

Respuestas:

6

Arquitectura InnoDB

Arquitectura InnoDB

ANÁLISIS

  • De alguna manera, perdiste los archivos my_user.frmy my_user.ibd. El diccionario de datos todavía tiene una entrada para esa tabla.
  • No se puede ejecutar DROP TABLE my_user;porque mysqld busca el my_user.frmprimero. Como esto es no my_user.frm, la tabla no se puede descartar.
  • Aunque my_user.frmno existe, no puede ejecutarlo CREATE TABLE my_user ...porque mysqld cree que está bien crear la tabla pero luego se desvía al motor de almacenamiento. InnoDB dice "Ya tengo el tablespace_id de my_user registrado".

Esta secuencia de eventos se puede probar si crea la tabla con MyISAM. mysqld lo permitirá. Una vez que cambia a InnoDB, vuelve directamente al diccionario de datos, que es defectuoso en esa entrada.

Tengo dos sugerencias

SUGERENCIA # 1

No crees más la tabla con ese nombre. Use un nombre de tabla diferente

CREATE TABLE my_usertable (id INT AUTO_INCREMENT NOT NULL, username VARCHAR(255), group_id VARCHAR(255) DEFAULT NULL, PRIMARY KEY(id)) DEFAULT CHARACTER SET utf8 COLLATE utf8_unicode_ci ENGINE = InnoDB;

Esto hará que cambie el nombre de la tabla en el código de su aplicación

SUGERENCIA # 2

He tratado este problema antes en mi tabla InnoDB posterior. SELECT devuelve ERROR 2006 (HY000): el servidor MySQL se ha ido (después de un corte de energía)

RolandoMySQLDBA
fuente
# 1 Gran respuesta, gracias por los detalles. # 2 Mysqldump (ed), detuvo mysqld, eliminó ibdata1, luego reinició, pero no puedo hacer que el demonio se inicie con éxito nuevamente. Necesito entender mejor lo que está pasando.
Sangrado el
Ok, todo funciona ahora. También tuvo que eliminar ib_logfile0y ib_logfile1(junto con ibdata1). Después de la importación, pude crear la my_usertabla sin ningún problema. Gracias Rolando!
Sangrado el
He perdido otras dos mesas ahora. Estoy grabando cada consulta ejecutada y esas tablas no se eliminaron usando DROP TABLE. Algo está pasando mal.
Sangrado el
5

Solo para agregar mi solución ya que tuve un problema similar.

TL; DR

  • Recree la tabla con la misma especificación de clave externa pero con un nombre diferente al que tenía anteriormente la tabla.
  • Descarte la tabla resultante (también descartará la clave foránea huérfana original)
  • Recrear tabla con clave original o sin clave foránea

Detalle

Me encontré con la desagradable situación en la que falló una declaración ALTER TABLE debido a que una clave externa no se eliminó antes. Esto llevó a algunas inconsistencias en el diccionario de datos InnoDB (probablemente debido a http://bugs.mysql.com/bug.php?id=58215 ).

Pregunta relacionada aquí: /programming/16857451/error-in-foreign-key-constraint-on-a-droped-table

mysql> ALTER TABLE `visits` CHANGE COLUMN `variation_visitor_id` `variation_visitor_id` INT(11) NOT NULL  ;

Error al cambiar el nombre de './db/#sql-482c_8448f' a './db/visits' (errno: 150)

mysql> SHOW ENGINE INNODB STATUS;

Error in foreign key constraint of table db/visits:
 FOREIGN KEY (`variation_visitor_id`) REFERENCES `variations_visitors` (`id`) ON DELETE NO ACTION ON UPDATE NO ACTION
) ENGINE=InnoDB DEFAULT CHARSET=utf8
Cannot find an index in the referenced table where the
referenced columns appear as the first columns, or column types
in the table and the referenced table do not match for constraint.
Note that the internal storage type of ENUM and SET changed in
tables created with >= InnoDB-4.1.12, and such columns in old tables
cannot be referenced by such columns in new tables.
See http://dev.mysql.com/doc/refman/5.5/en/innodb-foreign-key-constraints.html 
for correct foreign key definitippon.

Como no pude recuperar la tabla # sql-482c_8448f para las visitas, decidí volver a importarla desde una copia de seguridad realizada justo antes del alter. Sin embargo esto falló. En investigación:

  • La restricción se había eliminado de INFORMATION_SCHEMA.TABLE_CONSTRAINTS y ​​INFORMATION_SCHEMA.STATISTICS
  • Pero la restricción aún era visible en INFORMATION_SCHEMA.INNODB_SYS_FOREIGN;
  • La tabla no existía, así que no pude soltar la clave externa
  • No pude crear la tabla sin errores

SQL / Errores

mysql> SELECT * FROM INFORMATION_SCHEMA.INNODB_SYS_FOREIGN WHERE ID='db/fk_visits_variations_visitors1';

+-----------------------------------+-----------+------------------------+--------+------+
| ID                                | FOR_NAME  | REF_NAME               | N_COLS | TYPE |
+-----------------------------------+-----------+------------------------+--------+------+
| db/fk_visits_variations_visitors1 | db/visits | db/variations_visitors |      1 |   48 |
+-----------------------------------+-----------+------------------------+--------+------+

Intentar recrear la tabla sin la clave externa causó un error 150

mysql>

SET UNIQUE_CHECKS = 0;
SET FOREIGN_KEY_CHECKS = 0;

CREATE TABLE `visits` (
  `id` INT(11) NOT NULL AUTO_INCREMENT  ,
  `variation_visitor_id` INT(11) NOT NULL  ,
  PRIMARY KEY (`id`),
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

SET FOREIGN_KEY_CHECKS = 1;
SET UNIQUE_CHECKS = 1;

ERROR 1005 (HY000) at line 26: Can't create table 'db.visits' (errno: 150)

mysql> SHOW ENGINE INNODB STATUS;

Error in foreign key constraint of table db/visits:
there is no index in the table which would contain
the columns as the first columns, or the data types in the
table do not match the ones in the referenced table
or one of the ON ... SET NULL columns is declared NOT NULL. Constraint:
,
  CONSTRAINT "fk_visits_variations_visitors1" FOREIGN KEY ("variation_visitor_id") REFERENCES "variations_visitors" ("id") ON DELETE NO ACTION ON UPDATE NO ACTION

Intentar crearlo provocó un error 121

mysql>

SET UNIQUE_CHECKS = 0;
SET FOREIGN_KEY_CHECKS = 0;

CREATE TABLE `visits` (
  `id` INT(11) NOT NULL AUTO_INCREMENT  ,
  `variation_visitor_id` INT(11) NOT NULL  ,
  PRIMARY KEY (`id`),
  KEY `fk_visits_variations_visitors1` (`variation_visitor_id`),
  CONSTRAINT `fk_visits_variations_visitors1` FOREIGN KEY (`variation_visitor_id`) REFERENCES `variations_visitors` (`id`) ON DELETE NO ACTION ON UPDATE NO ACTION
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

SET FOREIGN_KEY_CHECKS = 1;
SET UNIQUE_CHECKS = 1;

ERROR 1005 (HY000) at line 26: Can't create table 'db.visits' (errno: 121)

mysql> SHOW ENGINE INNODB STATUS;

Error in foreign key constraint creation for table `db`.`visits`.
A foreign key constraint of name `db`.`fk_visits_variations_visitors1`
already exists. (Note that internally InnoDB adds 'databasename'
in front of the user-defined constraint name.)
Note that InnoDB's FOREIGN KEY system tables store
constraint names as case-insensitive, with the
MySQL standard latin1_swedish_ci collation. If you
create tables or databases whose names differ only in
> the character case, then collisions in constraint
names can occur. Workaround: name your constraints
explicitly with unique names.

Finalmente utilicé un nuevo nombre de clave externa. No esperaba que esto funcionara, pero permitió que se creara la tabla.

mysql>

SET UNIQUE_CHECKS = 0;
SET FOREIGN_KEY_CHECKS = 0;

CREATE TABLE `visits` (
  `id` INT(11) NOT NULL AUTO_INCREMENT  ,
  `variation_visitor_id` INT(11) NOT NULL  ,
  PRIMARY KEY (`id`),
  KEY `fk_visits_variations_visitors2` (`variation_visitor_id`),
  CONSTRAINT `fk_visits_variations_visitors2` FOREIGN KEY (`variation_visitor_id`) REFERENCES `variations_visitors` (`id`) ON DELETE NO ACTION ON UPDATE NO ACTION
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

SET FOREIGN_KEY_CHECKS = 1;
SET UNIQUE_CHECKS = 1;

Simplemente soltar la tabla después de eso eliminó el registro errante en INFORMATION_SCHEMA.INNODB_SYS_FOREIGN, lo que permite una importación con el nombre de la clave externa original.

Mark C
fuente
1

Hay una forma simple de evitar esto, aunque es cierto que, en ciertas circunstancias, es posible que no desee hacer esto. Dado que este problema se deriva de una referencia interna de InnoDB, simplemente puede crear esta tabla con el mismo nombre, las mismas columnas, solo con un motor de almacenamiento diferente. Me encontré con esto en un esclavo MySQL, y aunque el maestro del que estaba replicando era InnoDB, volví a crear esta tabla con MyISAM y pude volver a funcionar. Elegí específicamente InnoDB para mi motor de almacenamiento en el maestro, y en algunas tablas, también sería importante en el esclavo, pero en este caso, no tuvo ningún impacto en este esclavo para esta tabla, por lo que fue una forma rápida para solucionar este problema. Eliminar toda la base de datos habría sido un proyecto mucho más grande.

Desarrollador de bienes raíces
fuente
0

Lo que funcionó para mí fue:

  • primero mueva los archivos .frm y .ibd a otro directorio, por ejemplo / tmp / tablebackup *
  • ahora extrayendo la estructura de la tabla del archivo .frm usando mysqlfrmde Oracle mysql-utitilies** (porque no tenía otra copia / copia de seguridad de la estructura), por ejemplo:/usr/bin/mysqlfrm --diagnostic /tmp/tablebackup/MyTable.frm
  • crear una nueva tabla con la estructura de la tabla original pero con un nombre diferente (por ejemplo, supongamos que la tabla con el problema es MyTableque ahora creé una tabla MyTableBcon la estructura de la tabla original)
  • luego cambie el nombre de la tabla al nombre original desde mysql, por ejemplo: RENAME TABLE `MyTableB` TO `MyTable`;(tenga en cuenta que esto solo funciona si no lo ha innodb_force_recoveryconfigurado en su my.cnf)
  • ahora en mysql ejecuta: ALTER TABLE `MyTable` DISCARD TABLESPACE;
  • luego copie el .ibdarchivo original (solo el archivo .ibd, no el archivo .frm) nuevamente en el directorio de la base de datos mysql desde donde se movió originalmente (no debería haber un archivo .ibd existente en este momento porque eso se elimina por el DISCARD TABLESPACEmando)
  • y ahora corre ALTER TABLE `MyTable` IMPORT TABLESPACE;

* Reinicé mysql después de este paso, pero no estoy seguro de que sea necesario

** mysql-utilities pueden requerir instalación mysql-connector-pythonprimero

Arturo
fuente
0

Perdió datos de la tabla, pero el registro sobre esta tabla todavía existe en "mysql / data / ibdata1". La solución más fácil es crear esta tabla en alguna otra base de datos y luego copiar archivos:

mysql/data/**dummy_database**/my_user.frm

mysql/data/**dummy_database**/my_user.ibd

a los tuyos:

mysql/data/**yours_database**/my_user.frm

mysql/data/**yours_database**/my_user.ibd
Hevyweb
fuente