Impossible de créer une table, mais la table n'existe pas

11

J'utilise ces étapes pour créer une table my_user, qui existait déjà mais qui a en quelque sorte disparu de ma base de données 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)

J'ai essayé # mysqladmin flush-tableset répété les étapes ci-dessus mais cela n'a pas été utile. En outre, redémarré le mysqlservice, mais pas bon.

Des idées? Google m'a échoué jusqu'à présent. Merci.

Informaitons supplémentaires:

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")
saigner
la source
1
Êtes-vous sûr de ne pas avoir de faute de frappe quelque part? Vous dites que vous créez une table my_usermais l'erreur concerne my_db.user...
mustaccio
@mustaccio, yep a fait une faute de frappe lors du raccourcissement du nom de la table en my_user (l'original a un nom plus long et confus). En fait, le CREATE TABLEcode est généré par la bibliothèque Doctrine ORM (PHP).
noisebleed
Donc, ce ne sont pas les noms réels, vous nous
taquinez
si vous avez abandonné l'enregistrement dans le dictionnaire InnoDB, il ne vous permettra pas de créer une table avec le même nom. Ressemble à votre cas, mais a besoin de plus d'enquête. Essayez de mettre de faux my_user.frm et my_user.ibd et déposez le tableau.
akuzminsky
Le nom réel de la table a-t-il un caractère étrange (pas alphanumérique)? Cela commence-t-il par un chiffre ou un caractère étrange?
ypercubeᵀᴹ

Réponses:

6

Architecture InnoDB

Architecture InnoDB

UNE ANALYSE

  • D'une manière ou d'une autre, vous avez perdu les fichiers my_user.frmet my_user.ibd. Le dictionnaire de données a toujours une entrée pour cette table.
  • Vous ne pouvez pas exécuter DROP TABLE my_user;car mysqld recherche le my_user.frmpremier. Comme ce n'est pas le cas my_user.frm, le tableau ne peut pas être supprimé.
  • Bien qu'il my_user.frmn'existe pas, vous ne pouvez pas exécuter CREATE TABLE my_user ...car mysqld pense qu'il est OK de créer la table, mais passe ensuite au moteur de stockage. InnoDB dit "J'ai déjà enregistré le tablespace_id de my_user".

Cette séquence d'événements peut être prouvée si vous créez la table à l'aide de MyISAM. mysqld le permettra. Une fois que vous passez à InnoDB, il revient directement au dictionnaire de données, qui est défectueux sur cette seule entrée.

J'ai deux suggestions

SUGGESTION # 1

Ne créez plus la table avec ce nom. Utilisez un nom de table différent

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;

Cela vous amènera à changer le nom de la table dans votre code d'application

SUGGESTION # 2

J'ai déjà traité ce problème dans mon article. La table InnoDB SELECT renvoie ERREUR 2006 (HY000): le serveur MySQL est parti (après une panne de courant)

RolandoMySQLDBA
la source
# 1 Excellente réponse, merci pour les détails. # 2 Mysqldump (ed), a arrêté mysqld, supprimé ibdata1, puis redémarré mais ne peut pas redémarrer le démon avec succès. Besoin de mieux comprendre ce qui se passe.
noisebleed
Ok, tout fonctionne maintenant. Dû également supprimer ib_logfile0et ib_logfile1(avec ibdata1). Après l'importation, j'ai pu créer la my_usertable sans aucun problème. Merci Rolando!
noisebleed
J'ai perdu deux autres tables maintenant. J'enregistre chaque requête exécutée et ces tables n'ont pas été supprimées à l'aide DROP TABLE. Quelque chose ne va pas.
noisebleed
5

Juste pour ajouter ma solution car j'ai eu un problème similaire.

TL; DR

  • Recréez la table avec la même spécification de clé étrangère mais avec un nom différent de celui détenu précédemment par la table.
  • Supprimez la table résultante (supprimera également la clé étrangère orpheline d'origine)
  • Recréer une table avec une clé étrangère originale ou sans clé étrangère

Détail

J'ai rencontré la situation désagréable où une instruction ALTER TABLE a échoué car une clé étrangère n'a pas été supprimée plus tôt. Cela a conduit à des incohérences dans le dictionnaire de données InnoDB (probablement en raison de http://bugs.mysql.com/bug.php?id=58215 ).

Question connexe ici: /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  ;

Erreur lors du renommage de './db/#sql-482c_8448f' en './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.

Comme je n'ai pas pu récupérer la table # sql-482c_8448f aux visites, j'ai décidé de la réimporter à partir d'une sauvegarde effectuée juste avant la modification. Mais cela a échoué. Enquête:

  • La contrainte a été supprimée de INFORMATION_SCHEMA.TABLE_CONSTRAINTS et INFORMATION_SCHEMA.STATISTICS
  • Mais la contrainte était toujours visible dans INFORMATION_SCHEMA.INNODB_SYS_FOREIGN;
  • La table n'existait pas, je n'ai donc pas pu supprimer la clé étrangère
  • Je n'ai pas pu créer la table sans erreur

SQL / Erreurs

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 |
+-----------------------------------+-----------+------------------------+--------+------+

La tentative de recréation de la table sans la clé étrangère a provoqué une erreur 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

Essayer de le créer avec a provoqué une erreur 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.

Finalement, j'ai utilisé un nouveau nom de clé étrangère. Je ne m'attendais pas à ce que cela fonctionne, mais cela a permis de créer la table.

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;

Il suffit de supprimer la table après avoir supprimé l'enregistrement erroné dans INFORMATION_SCHEMA.INNODB_SYS_FOREIGN, permettant une importation avec le nom de clé étrangère d'origine.

Mark C
la source
1

Il existe un moyen simple de contourner ce problème, mais il est vrai que, dans certaines circonstances, vous pouvez ne pas vouloir le faire. Étant donné que ce problème découle d'une référence interne InnoDB, vous pouvez simplement créer cette table avec le même nom, les mêmes colonnes, en utilisant uniquement un moteur de stockage différent. J'ai rencontré cela sur un esclave MySQL, et même si le maître à partir duquel je répliquais était InnoDB, j'ai recréé cette seule table avec MyISAM et j'ai pu me remettre en marche. J'ai spécifiquement choisi InnoDB pour mon moteur de stockage sur le maître, et sur certaines tables, ce serait également important pour l'esclave, mais dans ce cas, cela n'a eu aucun impact sur cet esclave pour cette seule table, donc c'était un moyen rapide pour contourner ce problème. Supprimer toute la base de données aurait été un projet beaucoup plus important.

Promoteur immobilier
la source
0

Ce qui a fonctionné pour moi, c'est:

  • déplacez d'abord les fichiers .frm et .ibd dans un autre répertoire, par exemple / tmp / tablebackup *
  • extraire maintenant la structure de la table du fichier .frm à l'aide mysqlfrmd'Oracle mysql-utitilies** (car je n'avais pas d'autre copie / sauvegarde de la structure) par exemple:/usr/bin/mysqlfrm --diagnostic /tmp/tablebackup/MyTable.frm
  • créer une nouvelle table avec la structure de la table d'origine mais avec un nom différent (par exemple, disons que la table avec le problème est MyTablealors j'ai maintenant créé une table MyTableBavec la structure de la table d'origine)
  • Renommez ensuite la table au nom d' origine à partir de MySQL, par exemple: RENAME TABLE `MyTableB` TO `MyTable`;(notez que cela ne fonctionne que si vous ne pas avoir innodb_force_recoverydéfini dans votre my.cnf)
  • maintenant dans mysql run: ALTER TABLE `MyTable` DISCARD TABLESPACE;
  • puis copiez le .ibdfichier d' origine (uniquement le fichier .ibd, pas le fichier .frm) dans le répertoire de base de données mysql d'où il a été initialement déplacé (il ne devrait pas y avoir de fichier .ibd existant pour le moment car il est supprimé par le DISCARD TABLESPACEcommander)
  • et maintenant courir ALTER TABLE `MyTable` IMPORT TABLESPACE;

* J'ai redémarré mysql après cette étape mais je ne suis pas sûr que cela soit nécessaire

** Les utilitaires mysql peuvent nécessiter une installation mysql-connector-pythonpréalable

Arthur
la source
0

Vous avez perdu les données de la table, mais l'enregistrement sur cette table existe toujours dans "mysql / data / ibdata1". La solution la plus simple consiste à créer cette table dans une autre base de données, puis à copier des fichiers:

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

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

à vous:

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

mysql/data/**yours_database**/my_user.ibd
Hevyweb
la source