Não é possível criar a tabela, mas a tabela não existe

11

Estou usando estas etapas para criar uma tabela my_user, que já existia, mas desapareceu de alguma forma do meu banco de dados 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)

Tentei # mysqladmin flush-tablese repeti as etapas acima, mas não foi útil. Além disso, reiniciou o mysqlserviço, mas não é bom.

Alguma ideia? O Google falhou comigo até agora. Obrigado.

Informação 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")
noisebleed
fonte
11
Tem certeza de que não tem um erro de digitação em algum lugar? Você diz que está criando a tabela my_user, mas o erro é de cerca de my_db.user...
mustaccio
@mustaccio, sim, cometeu um erro de digitação ao encurtar o nome da tabela para my_user (o original tem um nome mais longo e confuso). Na verdade, o CREATE TABLEcódigo é gerado pela biblioteca Doctrine ORM (PHP).
noisebleed
Assim, estes não são os nomes reais, você está apenas provocando-nos ...
mustaccio
se você abandonou o registro no dicionário InnoDB, não permitirá que você crie uma tabela com o mesmo nome. Parece o seu caso, mas precisa de mais investigação. Tente colocar my_user.frm e my_user.ibd falsos e solte a tabela.
akuzminsky
O nome da tabela real tem algum caractere estranho (não alfanumérico)? Começa com um dígito ou um caractere estranho?
ypercubeᵀᴹ

Respostas:

6

Arquitetura InnoDB

Arquitetura InnoDB

ANÁLISE

  • De alguma forma, você perdeu os arquivos my_user.frme my_user.ibd. O dicionário de dados ainda tem uma entrada para essa tabela.
  • Você não pode executar DROP TABLE my_user;porque o mysqld procura o my_user.frmprimeiro. Como não my_user.frm, a tabela não pode ser descartada.
  • Embora my_user.frmnão exista, você não pode executar CREATE TABLE my_user ...porque o mysqld acha que é bom criar a tabela, mas depois adia para o mecanismo de armazenamento. O InnoDB diz "Eu já tenho o tablespace_id do meu_usuário registrado".

Essa sequência de eventos pode ser comprovada se você criar a tabela usando o MyISAM. O mysqld permitirá isso. Depois de alternar para o InnoDB, ele volta ao dicionário de dados, que está com defeito nessa entrada.

Tenho duas sugestões

SUGESTÃO # 1

Não crie mais a tabela com esse nome. Use um nome de tabela 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;

Isso resultará na alteração do nome da tabela no código do aplicativo

SUGESTÃO # 2

Eu lidei com esse problema antes na minha tabela InnoDB SELECT retorna ERRO 2006 (HY000): O servidor MySQL se foi (após uma queda de energia)

RolandoMySQLDBA
fonte
# 1 Ótima resposta, obrigado pelos detalhes. # 2 Mysqldump (ed), parou o mysqld, removeu o ibdata1 e reiniciou, mas não conseguiu que o daemon iniciasse com êxito novamente. Precisa entender melhor o que está acontecendo.
Noisebleed
Ok, tudo funcionando agora. Tinha que também remover ib_logfile0e ib_logfile1(junto com ibdata1). Após a importação, eu poderia criar a my_usertabela sem problemas. Obrigado Rolando!
noisebleed
Eu perdi duas outras mesas agora. Estou gravando todas as consultas executadas e essas tabelas não foram removidas usando DROP TABLE. Algo errado está acontecendo.
noisebleed
5

Apenas para adicionar minha solução, pois tive um problema semelhante.

TL; DR

  • Recrie a tabela com a mesma especificação de chave estrangeira, mas com um nome diferente, como anteriormente mantido pela tabela.
  • Solte a tabela resultante (também soltará a chave estrangeira órfã original)
  • Recriar tabela com original ou sem chave estrangeira

Detalhe

Corri para a situação desagradável em que uma instrução ALTER TABLE falhou devido a uma chave estrangeira não ter sido descartada anteriormente. Isso levou a algumas inconsistências no dicionário de dados do InnoDB (provavelmente devido a http://bugs.mysql.com/bug.php?id=58215 ).

Pergunta relacionada aqui: /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  ;

Erro ao renomear './db/#sql-482c_8448f' para './db/visits' (número de erro: 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 não consegui recuperar a tabela # sql-482c_8448f para visitas, decidi reimportá-la de um backup feito pouco antes da alteração. No entanto, isso falhou. Na investigação:

  • A restrição foi removida de INFORMATION_SCHEMA.TABLE_CONSTRAINTS e INFORMATION_SCHEMA.STATISTICS
  • Mas a restrição ainda estava visível em INFORMATION_SCHEMA.INNODB_SYS_FOREIGN;
  • A tabela não existia, então não pude soltar a chave estrangeira
  • Não consegui criar a tabela sem erros

SQL / Erros

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

Tentando recriar a tabela sem a chave estrangeira causou erro ane 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

A tentativa de criá-lo causou um erro 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.

Eventualmente, usei um novo nome de chave estrangeira. Eu não esperava que isso funcionasse, mas permitiu a criação da tabela.

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;

Simplesmente soltar a tabela depois disso removeu o registro incorreto em INFORMATION_SCHEMA.INNODB_SYS_FOREIGN, permitindo uma importação com o nome da chave estrangeira original.

Mark C
fonte
1

Existe uma maneira simples de contornar isso, embora seja certo que, em certas circunstâncias, você pode não querer fazer isso. Como esse problema decorre de uma referência interna do InnoDB, você pode simplesmente criar esta tabela com o mesmo nome, as mesmas colunas, usando apenas um mecanismo de armazenamento diferente. Eu me deparei com isso em um escravo do MySQL e, mesmo que o mestre do qual eu estava replicando fosse o InnoDB, recriei essa tabela com o MyISAM e consegui voltar a funcionar. Escolhi especificamente o InnoDB para o meu mecanismo de armazenamento no mestre e, em algumas tabelas, isso também seria importante para o escravo, mas, nesse caso, não causou nenhum impacto nesse escravo para essa tabela, por isso foi uma maneira rápida para contornar esse problema. Descartar todo o banco de dados teria sido um projeto muito maior.

Incorporador de imóveis
fonte
0

O que funcionou para mim foi:

  • primeiro mova os arquivos .frm e .ibd para outro diretório, por exemplo, / tmp / tablebackup *
  • agora extraindo a estrutura da tabela do arquivo .frm usando mysqlfrmdo Oracle mysql-utitilies** (porque eu não tinha outra cópia / backup da estrutura), por exemplo:/usr/bin/mysqlfrm --diagnostic /tmp/tablebackup/MyTable.frm
  • crie uma nova tabela com a estrutura da tabela original, mas com um nome diferente (por exemplo, digamos que a tabela com o problema seja MyTableentão, agora criei uma tabela MyTableBcom a estrutura da tabela original)
  • Em seguida, renomeie a tabela para o nome original no mysql, por exemplo: RENAME TABLE `MyTableB` TO `MyTable`;(observe que isso só funciona se você não tiver innodb_force_recoverydefinido no seumy.cnf )
  • agora no mysql execute: ALTER TABLE `MyTable` DISCARD TABLESPACE;
  • copie o .ibdarquivo original (somente o arquivo .ibd, não o arquivo .frm) de volta para o diretório do banco de dados mysql de onde foi originalmente movido (não deve haver um arquivo .ibd existente no momento, porque isso é removido pelo DISCARD TABLESPACEcomando)
  • e agora corra ALTER TABLE `MyTable` IMPORT TABLESPACE;

* Reiniciei o mysql após esta etapa, mas não tenho certeza se isso é necessário

** o mysql-utilities pode exigir a instalação mysql-connector-pythonprimeiro

Arthur
fonte
0

Você perdeu os dados da tabela, mas o registro sobre esta tabela ainda existe em "mysql / data / ibdata1". A solução mais fácil é criar esta tabela em outro banco de dados e copiar arquivos:

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

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

para o seu próprio:

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

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