Impossibile creare la tabella, ma la tabella non esiste


11

Sto usando questi passaggi per creare una tabella my_user, che esisteva già ma che in qualche modo è scomparsa dal mio database 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)

Ho provato # mysqladmin flush-tablese ripetuto i passaggi precedenti ma non è stato utile. Inoltre, riavviato il mysqlservizio, ma non va bene.

Qualche idea? Finora Google mi ha deluso. Grazie.

Informazioni 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")

1
Sei sicuro di non avere un refuso da qualche parte? Dici che stai creando una tabella my_userma l'errore riguarda my_db.user...
Mustaccio

@mustaccio, sì, ho fatto un refuso quando accorciavo il nome della tabella in my_user (l'originale ha un nome più lungo e confuso). In realtà il CREATE TABLEcodice è generato dalla libreria Doctrine ORM (PHP).
Rumorosamente il

Quindi, questi non sono i nomi reali, ci stai solo prendendo in giro ...
Mustaccio,

se hai abbandonato i record nel dizionario InnoDB non ti permetterà di creare una tabella con lo stesso nome. Sembra il tuo caso, ma necessita di ulteriori indagini. Prova a mettere falsi my_user.frm e my_user.ibd e rilascia la tabella.
Akuzminsky,

Il nome effettivo della tabella ha caratteri strani (non alfanumerici)? Comincia con una cifra o un personaggio strano?
ypercubeᵀᴹ

Risposte:


6

Architettura di InnoDB

Architettura di InnoDB

ANALISI

  • In qualche modo, hai perso i file my_user.frme my_user.ibd. Il dizionario dei dati ha ancora una voce per quella tabella.
  • Non puoi eseguire DROP TABLE my_user;perché mysqld cerca il my_user.frmprimo. Poiché questo è no my_user.frm, la tabella non può essere eliminata.
  • Sebbene my_user.frmnon esista, non puoi eseguirlo CREATE TABLE my_user ...perché mysqld pensa che sia giusto creare la tabella ma poi passa al motore di archiviazione. InnoDB dice "Ho già registrato tablespace_id di my_user".

Questa sequenza di eventi può essere dimostrata se si crea la tabella utilizzando MyISAM. mysqld lo permetterà. Una volta passato a InnoDB, torna al dizionario dei dati, che è difettoso in quella voce.

Ho due suggerimenti

SUGGERIMENTO # 1

Non creare più la tabella con quel nome. Usa un nome di tabella diverso

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;

Ciò comporterà la modifica del nome della tabella nel codice dell'applicazione

SUGGERIMENTO # 2

Ho già affrontato questo problema nel mio post Tabella InnoDB SELECT restituisce ERRORE 2006 (HY000): il server MySQL è andato via (dopo un'interruzione di corrente)


# 1 Ottima risposta, grazie per i dettagli. # 2 Mysqldump (ed), arrestato mysqld, rimosso ibdata1, quindi riavviato ma non è possibile riavviare correttamente il daemon. Ho bisogno di capire meglio cosa sta succedendo.
Rumorosamente il

Ok, ora funziona tutto. Ho dovuto anche rimuovere ib_logfile0e ib_logfile1(insieme a ibdata1). Dopo l'importazione ho potuto creare la my_usertabella senza problemi. Grazie Rolando!
Rumorosamente il

Ho perso altri due tavoli ora. Sto registrando ogni query eseguita e quelle tabelle non sono state rimosse utilizzando DROP TABLE. Sta succedendo qualcosa di sbagliato.
Rumorosamente il

5

Solo per aggiungere la mia soluzione perché avevo un problema simile.

TL; DR

  • Ricreare la tabella con la stessa specifica di chiave esterna ma con un nome diverso da quello precedentemente detenuto dalla tabella.
  • Elimina la tabella risultante (eliminerà anche la chiave esterna orfana originale)
  • Ricrea tabella con chiave esterna originale o nessuna

Dettaglio

Mi sono imbattuto nella brutta situazione in cui un'istruzione ALTER TABLE non è riuscita a causa di una chiave esterna che non è stata rilasciata in precedenza. Ciò ha portato ad alcune incongruenze nel dizionario dei dati InnoDB (probabilmente dovuto a http://bugs.mysql.com/bug.php?id=58215 ).

Domanda correlata qui: /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  ;

Errore nella ridenominazione di './db/#sql-482c_8448f' in './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.

Dato che non riuscivo a ripristinare la tabella # sql-482c_8448f alle visite, ho deciso di reimportarla da un backup eseguito appena prima della modifica. Tuttavia questo non è riuscito. Su indagine:

  • Il vincolo era stato rimosso da INFORMATION_SCHEMA.TABLE_CONSTRAINTS e INFORMATION_SCHEMA.STATISTICS
  • Ma il vincolo era ancora visibile in INFORMATION_SCHEMA.INNODB_SYS_FOREIGN;
  • La tabella non esisteva, quindi non ho potuto rilasciare la chiave esterna
  • Non ho potuto creare la tabella senza errori

SQL / Errori

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

Il tentativo di ricreare la tabella senza la chiave esterna ha causato un errore 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

Il tentativo di crearlo con ha causato un errore 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.

Alla fine ho usato un nuovo nome di chiave esterna. Non mi aspettavo che funzionasse, ma ha permesso la creazione della tabella.

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;

Trascinare semplicemente la tabella dopo aver rimosso il record errato in INFORMATION_SCHEMA.INNODB_SYS_FOREIGN, consentendo un'importazione con il nome della chiave esterna originale.


1

C'è un modo semplice per aggirare questo, anche se è vero, in determinate circostanze potresti non volerlo fare. Poiché questo problema deriva da un riferimento interno di InnoDB, puoi semplicemente creare questa tabella con lo stesso nome, le stesse colonne, usando solo un motore di archiviazione diverso. Mi sono imbattuto in questo su uno slave MySQL e anche se il master da cui stavo replicando era InnoDB, ho ricreato questa tabella con MyISAM e sono stato in grado di tornare in esecuzione. Ho scelto InnoDB specificamente per il mio motore di archiviazione sul master e su alcuni tavoli, sarebbe importante anche sullo slave, ma in questo caso non ha avuto alcun impatto su questo slave per questo unico tavolo, quindi è stato un modo rapido per aggirare questo problema. Eliminare l'intero database sarebbe stato un progetto molto più grande.


0

Ciò che ha funzionato per me è stato:

  • spostare prima i file .frm e .ibd in un'altra directory, ad esempio / tmp / tablebackup *
  • ora estraendo la struttura della tabella dal file .frm usando mysqlfrmda Oracle mysql-utitilies** (perché non avevo altre copie / backup della struttura) ad esempio:/usr/bin/mysqlfrm --diagnostic /tmp/tablebackup/MyTable.frm
  • creare una nuova tabella con la struttura della tabella originale ma con un nome diverso (ad esempio, supponiamo che la tabella con il problema sia MyTableche ora ho creato una tabella MyTableBcon la struttura della tabella originale)
  • quindi rinominare la tabella con il nome originale da mysql, ad esempio: RENAME TABLE `MyTableB` TO `MyTable`;(nota che funziona solo se non hai innodb_force_recoveryimpostato il tuo my.cnf)
  • ora in mysql run: ALTER TABLE `MyTable` DISCARD TABLESPACE;
  • quindi copiare il .ibdfile originale (solo il file .ibd, non il file .frm) nuovamente nella directory del database mysql da cui è stato originariamente spostato (al momento non dovrebbe esserci un file .ibd esistente perché viene rimosso dal file DISCARD TABLESPACEcomando)
  • e ora corri ALTER TABLE `MyTable` IMPORT TABLESPACE;

* Ho riavviato mysql dopo questo passaggio ma non sono sicuro che sia necessario

** mysql-utilities potrebbe richiedere mysql-connector-pythonprima l' installazione


0

Hai perso i dati della tabella, ma il record relativo a questa tabella esiste ancora in "mysql / data / ibdata1". La soluzione più semplice è creare questa tabella in qualche altro database e quindi copiare i file:

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

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

per te:

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

mysql/data/**yours_database**/my_user.ibd
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.