Nie można utworzyć tabeli, ale tabela nie istnieje

11

Korzystam z tych kroków, aby utworzyć tabelę my_user, która już istniała, ale jakoś zniknęła z mojej bazy danych 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)

Próbowałem # mysqladmin flush-tablesi powtórzyłem powyższe kroki, ale nie było to pomocne. Zrestartowałem także mysqlusługę, ale nic dobrego.

Jakieś pomysły? Jak dotąd zawiodło mnie Google. Dzięki.

Informacje dodatkowe:

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")
zakłopotany
źródło
1
Czy na pewno nie masz gdzieś literówki? Mówisz, że tworzysz tabelę, my_userale błąd dotyczy my_db.user...
mustaccio,
@mustaccio, yep popełnił literówkę podczas skracania nazwy tabeli do mojego_użytkownika (oryginał ma dłuższą, mylącą nazwę). W rzeczywistości CREATE TABLEkod jest generowany przez bibliotekę Doctrine ORM (PHP).
noisebleed
Więc to nie są prawdziwe imiona, tylko
drażnisz się z
jeśli porzuciłeś rekord w słowniku InnoDB, nie pozwoli ci to stworzyć tabeli o tej samej nazwie. Wygląda jak twoja sprawa, ale wymaga więcej badań. Spróbuj umieścić fałszywe my_user.frm i my_user.ibd i upuść tabelę.
akuzminsky
Czy nazwa tabeli ma jakiś dziwny znak (nie alfanumeryczny)? Czy zaczyna się cyfrą czy dziwnym znakiem?
ypercubeᵀᴹ

Odpowiedzi:

7

Architektura InnoDB

Architektura InnoDB

ANALIZA

  • Jakoś zgubiłeś pliki my_user.frmi my_user.ibd. Słownik danych nadal ma wpis dla tej tabeli.
  • Nie możesz uruchomić, DROP TABLE my_user;ponieważ mysqld szuka my_user.frmpierwszego. Ponieważ nie my_user.frm, nie można upuścić tabeli.
  • Chociaż my_user.frmnie istnieje, nie można go uruchomić, CREATE TABLE my_user ...ponieważ mysqld uważa, że ​​można utworzyć tabelę, ale następnie odkłada silnik pamięci masowej. InnoDB mówi „Mam już zarejestrowany tablepace_id mojego_użytkownika”.

Tę sekwencję zdarzeń można udowodnić, jeśli utworzysz tabelę za pomocą MyISAM. mysqld pozwoli na to. Po przejściu na InnoDB wraca on do słownika danych, który jest wadliwy dla tego jednego wpisu.

Mam dwie sugestie

SUGESTIA # 1

Nie twórz już tabeli o tej nazwie. Użyj innej nazwy tabeli

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;

Spowoduje to zmianę nazwy tabeli w kodzie aplikacji

SUGESTIA # 2

Rozwiązałem ten problem wcześniej w moim poście Tabela InnoDB SELECT zwraca BŁĄD 2006 (HY000): Serwer MySQL zniknął (po awarii zasilania)

RolandoMySQLDBA
źródło
# 1 Świetna odpowiedź, dziękuję za szczegóły. # 2 Mysqldump (ed), zatrzymał mysqld, usunął ibdata1, a następnie uruchomił ponownie, ale nie może ponownie uruchomić demona. Musisz lepiej zrozumieć, co się dzieje.
noisebleed
Ok, wszystko działa teraz. Musiałem także usunąć ib_logfile0i ib_logfile1(wraz z ibdata1). Po imporcie mogłem utworzyć my_usertabelę bez żadnych problemów. Dziękuję Rolando!
noisebleed
Straciłem teraz dwa inne stoły. Nagrywam każde wykonane zapytanie i te tabele nie zostały usunięte przy użyciu DROP TABLE. Dzieje się coś złego.
noisebleed
dzięki. mają ten sam dokładny problem. Brakuje 1 tabeli w mojej bazie danych i nie mogę jej przywrócić z kopii zapasowej, ponieważ nie mogę utworzyć tabeli.
Gigih Aji Ibrahim
5

Wystarczy dodać moje rozwiązanie, ponieważ miałem podobny problem.

TL; DR

  • Odtwórz tabelę z tą samą specyfikacją klucza obcego, ale o innej nazwie niż poprzednio przechowywana w tabeli.
  • Upuść wynikową tabelę (spowoduje także upuszczenie oryginalnego sierocego klucza obcego)
  • Odtwórz tabelę z oryginalnym kluczem obcym lub bez klucza obcego

Szczegół

Natrafiłem na nieprzyjemną sytuację, w której instrukcja ALTER TABLE nie powiodła się z powodu wcześniejszego usunięcia klucza obcego. Doprowadziło to do pewnych niespójności w słowniku danych InnoDB (prawdopodobnie z powodu http://bugs.mysql.com/bug.php?id=58215 ).

Powiązane pytanie tutaj: /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  ;

Błąd przy zmianie nazwy „./db/#sql-482c_8448f” na „./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.

Ponieważ nie mogłem odzyskać tabeli # sql-482c_8448f do odwiedzin, postanowiłem zaimportować ją z kopii zapasowej wykonanej tuż przed zmianą. Jednak to się nie udało. W trakcie dochodzenia:

  • Ograniczenie zostało usunięte z INFORMACJE_SCHEMA.TABLE_CONSTRAINTS i INFORMACJE_SCHEMA.STATISTICS
  • Ale ograniczenie było nadal widoczne w INFORMACJE_SCHEMA.INNODB_SYS_FOREIGN;
  • Tabela nie istniała, więc nie mogłem upuścić klucza obcego
  • Nie można utworzyć tabeli bez błędów

SQL / błędy

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

Próba odtworzenia tabeli bez klucza obcego spowodowała błąd 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

Próba utworzenia go spowodowała błąd 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.

W końcu użyłem nowej nazwy klucza obcego. Nie spodziewałem się, że to zadziała, ale pozwoliło to na utworzenie tabeli.

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;

Po prostu upuszczenie tabeli po tym usunęło błędny rekord w INFORMACJE_SCHEMA.INNODB_SYS_FOREIGN, umożliwiając import z oryginalną nazwą klucza obcego.

Mark C.
źródło
1

Istnieje jeden prosty sposób na obejście tego, choć trzeba przyznać, że w pewnych okolicznościach możesz tego nie chcieć. Ponieważ ten problem wynika z wewnętrznego odwołania InnoDB, możesz po prostu utworzyć tę tabelę o tej samej nazwie i tych samych kolumnach, używając tylko innego silnika pamięci. Natknąłem się na to na slave MySQL i mimo że mistrzem, z którego replikowałem, był InnoDB, odtworzyłem tę jedną tabelę za pomocą MyISAM i mogłem ponownie uruchomić. Specjalnie wybrałem InnoDB dla mojego silnika pamięci masowej w systemie głównym, a na niektórych stołach byłoby to również ważne dla urządzenia podrzędnego, ale w tym przypadku miało to zerowy wpływ na to urządzenie podrzędne dla tego jednego stołu, więc był to szybki sposób obejść ten problem. Usunięcie całej bazy danych byłoby znacznie większym projektem.

Deweloper nieruchomości
źródło
0

Dla mnie zadziałało:

  • najpierw przenieś pliki .frm i .ibd do innego katalogu, np. / tmp / tablebackup *
  • teraz wyodrębniam strukturę tabeli z pliku .frm przy użyciu mysqlfrmz Oracle mysql-utitilies** (ponieważ nie miałem innej kopii / kopii struktury) np .:/usr/bin/mysqlfrm --diagnostic /tmp/tablebackup/MyTable.frm
  • utwórz nową tabelę ze strukturą oryginalnej tabeli, ale o innej nazwie (np. powiedzmy, że tabela z problemem to MyTableteraz utworzyłem tabelę MyTableBo strukturze oryginalnej tabeli)
  • następny zmienić nazwę tabeli do oryginalnej nazwy od wewnątrz mysql, np: RENAME TABLE `MyTableB` TO `MyTable`;(uwaga, że to działa tylko jeśli ma nie być innodb_force_recoveryustawiona w my.cnf)
  • teraz w mysql run: ALTER TABLE `MyTable` DISCARD TABLESPACE;
  • następnie skopiuj oryginalny .ibdplik (tylko plik .ibd, a nie plik .frm ) z powrotem do katalogu bazy danych mysql, z którego został pierwotnie przeniesiony (w tej chwili nie powinien istnieć plik .ibd, ponieważ zostanie on usunięty przez DISCARD TABLESPACEKomenda)
  • i teraz biegnij ALTER TABLE `MyTable` IMPORT TABLESPACE;

* Uruchomiłem ponownie mysql po tym kroku, ale nie jestem pewien, czy jest to wymagane

** Narzędzia mysql mogą wymagać instalacji w mysql-connector-pythonpierwszej kolejności

Artur
źródło
0

Straciłeś dane tabeli, ale rekord dotyczący tej tabeli nadal istnieje w „mysql / data / ibdata1”. Najłatwiejszym rozwiązaniem jest utworzenie tej tabeli w innej bazie danych, a następnie skopiowanie plików:

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

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

do własnego:

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

mysql/data/**yours_database**/my_user.ibd
Hevyweb
źródło