简体   繁体   English

mysql 8 (innodb) 新建索引的外键约束

[英]mysql 8 (innodb) foreign key constraints on newly created indexes

Suppose I have a table items假设我有一个表items
with columns id (PRIMARY), name(VARCHAR), section_id (BIGINT), updated_at (DATETIME) ,id (PRIMARY), name(VARCHAR), section_id (BIGINT), updated_at (DATETIME)

and a table sections with id (PRIMARY) .和一个带有id (PRIMARY)的表sections

Naturally, items.section_id is a foreign key that refers to sections.id .自然地, items.section_id是引用sections.id的外键。

Suppose there is an index on items of the columns (section_id, name) .假设列(section_id, name)items有一个索引。 I believe that if you tried to drop this index, you would get an error that it is needed in a foreign key constraint .我相信如果你试图删除这个索引,你会得到一个错误,指出它needed in a foreign key constraint I can accept this.我可以接受这个。

Now, I want to create a new index, like create index ix_section_id_id_updated_at on items (section_id, id, updated_at) .现在,我想创建一个新索引,例如create index ix_section_id_id_updated_at on items (section_id, id, updated_at) MySQL lets me do this, but if I go to drop this table, I get that same error: it fails, because it is needed in a foreign key constraint . MySQL 让我这样做,但是如果我 go 删除这个表,我会得到同样的错误:它失败了,因为它needed in a foreign key constraint

Why should this be?为什么会这样? It already has one index that can be used for this foreign key check.它已经有一个可用于此外键检查的索引。 Further, the error does NOT go away with set FOREIGN_KEY_CHECKS=0;此外,错误不会 go 远离set FOREIGN_KEY_CHECKS=0; . . Is there a way to force MySQL to not associate the new index with the foreign key, so that it is quick to drop?有没有办法强制MySQL不把新索引和外键关联起来,这样就快drop了? This is necessary because I will be running the migration on a production server with temporary downtime, and need to be able to quickly revert the migration in case of anything going wrong afterwards.这是必要的,因为我将在临时停机的生产服务器上运行迁移,并且需要能够在之后出现任何问题的情况下快速恢复迁移。

I can reproduce your issue if I don't create an index on section_id and allow mysql to do so on the creation of a foreign key(as described in the manual).如果我不在 section_id 上创建索引并允许 mysql 在创建外键时这样做(如手册中所述),我可以重现您的问题。 Adding a new index drops the auto generated key and if you then drop the new index an error is generated because of the requirement to have a key, and mysql does not auto generate one on a drop.. .添加新索引会删除自动生成的密钥,如果您随后删除新索引,则会由于需要密钥而生成错误,而 mysql 不会在删除时自动生成一个...。 If you manually generate a key on section_id this problem does not happen..and the newly created compound index drops successfully.如果你在 section_id 上手动生成一个键,这个问题就不会发生......并且新创建的复合索引成功删除。

drop table if exists items;
drop table if exists sections;

create table items(id int PRIMARY key, name varchar(3), section_id BIGINT, updated_at DATETIME);

create table sections(id bigint primary key);

alter table items
    add foreign key fk1(section_id) references sections(id);
    
show create table items;

CREATE TABLE `items` (  `id` int(11) NOT NULL,  
`name` varchar(3) DEFAULT NULL,  
`section_id` bigint(20) DEFAULT NULL, 
 `updated_at` datetime DEFAULT NULL,  
PRIMARY KEY (`id`),  
KEY `fk1` (`section_id`),  
CONSTRAINT `fk1` FOREIGN KEY (`section_id`) REFERENCES `sections` (`id`)) ENGINE=InnoDB DEFAULT CHARSET=latin1;

alter table items
    add key key1(section_id, name);

show create table items;

CREATE TABLE `items` (
  `id` int(11) NOT NULL,
  `name` varchar(3) DEFAULT NULL,
  `section_id` bigint(20) DEFAULT NULL,
  `updated_at` datetime DEFAULT NULL,
  PRIMARY KEY (`id`),
  KEY `key1` (`section_id`,`name`),
  CONSTRAINT `fk1` FOREIGN KEY (`section_id`) REFERENCES `sections` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;

and with manually generated key并使用手动生成的密钥

drop table if exists items;
drop table if exists sections;

create table items(id int PRIMARY key, name varchar(3), section_id BIGINT, updated_at DATETIME);

create table sections(id bigint primary key);


alter table items
    add key sid(section_id);
alter table items
    add foreign key fk1(section_id) references sections(id);
    
show create table items;

CREATE TABLE `items` (
  `id` int(11) NOT NULL,
  `name` varchar(3) DEFAULT NULL,
  `section_id` bigint(20) DEFAULT NULL,
  `updated_at` datetime DEFAULT NULL,
  PRIMARY KEY (`id`),
  KEY `sid` (`section_id`),
  CONSTRAINT `fk1` FOREIGN KEY (`section_id`) REFERENCES `sections` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1

alter table items
    add key key1(section_id, name);

show create table items;

CREATE TABLE `items` (
  `id` int(11) NOT NULL,
  `name` varchar(3) DEFAULT NULL,
  `section_id` bigint(20) DEFAULT NULL,
  `updated_at` datetime DEFAULT NULL,
  PRIMARY KEY (`id`),
  KEY `sid` (`section_id`),
  KEY `key1` (`section_id`,`name`),
  CONSTRAINT `fk1` FOREIGN KEY (`section_id`) REFERENCES `sections` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM