mysql有时会在添加新索引时删除旧索引? TL;博士
我们在虚拟机上看到,添加唯一索引会导致自动删除较旧的非唯一索引 我无法在任何其他机器上复制(尚未?),如果我复制了:mysql有时会在添加新索引时删除旧索引? TL;博士,mysql,Mysql,我们在虚拟机上看到,添加唯一索引会导致自动删除较旧的非唯一索引 我无法在任何其他机器上复制(尚未?),如果我复制了: mysql -e 'create db2' mysqldump db1 | mysql db2 在将新索引添加到db1,然后尝试在db2上添加索引之前,不会从db2中删除旧索引。时髦 我们有一个带有db1的机器快照,可以在现有的db1数据库中复制它 有人知道发生了什么吗?我们有脚本来自动添加/删除索引,但这开始失败,因为在这台机器上,旧索引不再存在 当转储/恢复周期导致问题消失
mysql -e 'create db2'
mysqldump db1 | mysql db2
在将新索引添加到db1,然后尝试在db2上添加索引之前,不会从db2中删除旧索引。时髦
我们有一个带有db1的机器快照,可以在现有的db1数据库中复制它
有人知道发生了什么吗?我们有脚本来自动添加/删除索引,但这开始失败,因为在这台机器上,旧索引不再存在
当转储/恢复周期导致问题消失时,就很难理解、再现并将问题简化为一个简单的示例
细节
在添加新索引之前(从showcreatetable
),有问题的表是这样的。注意monitoredTableRowID
键:
CREATE TABLE `cfgAttributeInstances` (
`ID` int(10) unsigned NOT NULL AUTO_INCREMENT,
`attributeID` int(10) unsigned DEFAULT NULL,
`nodeID` int(10) unsigned DEFAULT NULL,
`groupID` int(10) unsigned DEFAULT NULL,
`statisticID` int(10) unsigned DEFAULT NULL,
`nodeStatisticID` int(10) unsigned DEFAULT NULL,
`serviceID` int(10) unsigned DEFAULT NULL,
`nodeServiceID` int(10) unsigned DEFAULT NULL,
`nodeComponentID` int(10) unsigned DEFAULT NULL,
`syslogFilterID` int(10) unsigned DEFAULT NULL,
`value` varchar(255) NOT NULL DEFAULT '',
PRIMARY KEY (`ID`),
UNIQUE KEY `nodeID` (`nodeID`,`attributeID`),
UNIQUE KEY `groupID` (`groupID`,`attributeID`),
UNIQUE KEY `statisticID` (`statisticID`,`attributeID`),
UNIQUE KEY `nodeStatisticID` (`nodeStatisticID`,`attributeID`),
UNIQUE KEY `serviceID` (`serviceID`,`attributeID`),
UNIQUE KEY `nodeServiceID` (`nodeServiceID`,`attributeID`),
KEY `attributeID` (`attributeID`),
KEY `monitoredTableRowID` (`nodeComponentID`),
KEY `syslogFilterID` (`syslogFilterID`),
CONSTRAINT `cfgAttributeInstances_ibfk_1` FOREIGN KEY (`attributeID`) REFERENCES `cfgAttributes` (`ID`) ON DELETE CASCADE,
CONSTRAINT `cfgAttributeInstances_ibfk_2` FOREIGN KEY (`nodeID`) REFERENCES `cfgNodes` (`ID`) ON DELETE CASCADE,
CONSTRAINT `cfgAttributeInstances_ibfk_3` FOREIGN KEY (`groupID`) REFERENCES `cfgGroups` (`ID`) ON DELETE CASCADE,
CONSTRAINT `cfgAttributeInstances_ibfk_4` FOREIGN KEY (`statisticID`) REFERENCES `cfgStatistics` (`ID`) ON DELETE CASCADE,
CONSTRAINT `cfgAttributeInstances_ibfk_5` FOREIGN KEY (`nodeStatisticID`) REFERENCES `cfgNodeStatistics` (`ID`) ON DELETE CASCADE,
CONSTRAINT `cfgAttributeInstances_ibfk_6` FOREIGN KEY (`serviceID`) REFERENCES `cfgServices` (`ID`) ON DELETE CASCADE,
CONSTRAINT `cfgAttributeInstances_ibfk_7` FOREIGN KEY (`nodeServiceID`) REFERENCES `cfgNodeServices` (`ID`) ON DELETE CASCADE,
CONSTRAINT `cfgAttributeInstances_ibfk_8` FOREIGN KEY (`nodeComponentID`) REFERENCES `cfgNodeComponents` (`ID`) ON DELETE CASCADE,
CONSTRAINT `cfgAttributeInstances_ibfk_9` FOREIGN KEY (`syslogFilterID`) REFERENCES `cfgSyslogFilters` (`ID`) ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=latin1 COMMENT='CapMon Attribute instances';
我添加了以下索引:
ALTER TABLE cfgAttributeInstances ADD
UNIQUE new_nodeComponentID (nodeComponentID, attributeID)
添加该索引后,看起来是这样的:
CREATE TABLE `cfgAttributeInstances` (
`ID` int(10) unsigned NOT NULL AUTO_INCREMENT,
`attributeID` int(10) unsigned DEFAULT NULL,
`nodeID` int(10) unsigned DEFAULT NULL,
`groupID` int(10) unsigned DEFAULT NULL,
`statisticID` int(10) unsigned DEFAULT NULL,
`nodeStatisticID` int(10) unsigned DEFAULT NULL,
`serviceID` int(10) unsigned DEFAULT NULL,
`nodeServiceID` int(10) unsigned DEFAULT NULL,
`nodeComponentID` int(10) unsigned DEFAULT NULL,
`syslogFilterID` int(10) unsigned DEFAULT NULL,
`value` varchar(255) NOT NULL DEFAULT '',
PRIMARY KEY (`ID`),
UNIQUE KEY `nodeID` (`nodeID`,`attributeID`),
UNIQUE KEY `groupID` (`groupID`,`attributeID`),
UNIQUE KEY `statisticID` (`statisticID`,`attributeID`),
UNIQUE KEY `nodeStatisticID` (`nodeStatisticID`,`attributeID`),
UNIQUE KEY `serviceID` (`serviceID`,`attributeID`),
UNIQUE KEY `nodeServiceID` (`nodeServiceID`,`attributeID`),
UNIQUE KEY `new_nodeComponentID` (`nodeComponentID`,`attributeID`),
KEY `attributeID` (`attributeID`),
KEY `syslogFilterID` (`syslogFilterID`),
CONSTRAINT `cfgAttributeInstances_ibfk_1` FOREIGN KEY (`attributeID`) REFERENCES `cfgAttributes` (`ID`) ON DELETE CASCADE,
CONSTRAINT `cfgAttributeInstances_ibfk_2` FOREIGN KEY (`nodeID`) REFERENCES `cfgNodes` (`ID`) ON DELETE CASCADE,
CONSTRAINT `cfgAttributeInstances_ibfk_3` FOREIGN KEY (`groupID`) REFERENCES `cfgGroups` (`ID`) ON DELETE CASCADE,
CONSTRAINT `cfgAttributeInstances_ibfk_4` FOREIGN KEY (`statisticID`) REFERENCES `cfgStatistics` (`ID`) ON DELETE CASCADE,
CONSTRAINT `cfgAttributeInstances_ibfk_5` FOREIGN KEY (`nodeStatisticID`) REFERENCES `cfgNodeStatistics` (`ID`) ON DELETE CASCADE,
CONSTRAINT `cfgAttributeInstances_ibfk_6` FOREIGN KEY (`serviceID`) REFERENCES `cfgServices` (`ID`) ON DELETE CASCADE,
CONSTRAINT `cfgAttributeInstances_ibfk_7` FOREIGN KEY (`nodeServiceID`) REFERENCES `cfgNodeServices` (`ID`) ON DELETE CASCADE,
CONSTRAINT `cfgAttributeInstances_ibfk_8` FOREIGN KEY (`nodeComponentID`) REFERENCES `cfgNodeComponents` (`ID`) ON DELETE CASCADE,
CONSTRAINT `cfgAttributeInstances_ibfk_9` FOREIGN KEY (`syslogFilterID`) REFERENCES `cfgSyslogFilters` (`ID`) ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=latin1 COMMENT='CapMon Attribute instances';
但是嘿!monitoredTableRowID
索引到哪里去了
同样,我无法复制这一点。如果我执行mysqldump>dump.db
/mysql
循环,则monitoredTableRowID
不会消失
有什么想法吗?带有
nodeComponentD
的复合键会导致带有nodeComponentD
的非复合键在其使用的外键引用上下文中是冗余的。MySQL会自动删除冗余的隐式索引。该行为取决于列索引顺序,因为删除的索引将始终是定义的复合键中的第一列
该问题是由添加外键约束时创建的自动隐式索引以及SHOW CREATE TABLE
中显式定义的索引引起的,mysqldump
也使用该索引
如果已经存在一个显式的
在可支持外键的子表上定义的索引。
否则,MySQL将隐式创建外键索引
MySQL需要外键和引用键的索引,以便
外键检查可以很快,不需要扫描表。在
引用表时,必须有外键所在的索引
列按相同顺序列为第一列。这样的
索引在引用表上自动创建(如果没有)
存在。如果您创建了索引,则稍后可能会自动删除该索引
另一个可用于强制外键约束的索引。
索引名称
(如果给定)如前所述使用
转载
隐式键示例
注-未明确定义索引FK\u BAR\u FOO(FOO\u id)
结果
索引FK\u BAR\u FOO(FOO\u id)
在SHOW CREATE TABLE
中明确定义,但由MySQL隐式创建
CREATE TABLE `BAR` (
`id` INT(11) NOT NULL,
`foo_id` INT(11) NOT NULL,
`b` INT(11) NOT NULL,
PRIMARY KEY (`id`),
INDEX `FK_BAR_FOO` (`foo_id`),
CONSTRAINT `FK_BAR_FOO` FOREIGN KEY (`foo_id`) REFERENCES `FOO` (`id`) ON DELETE CASCADE
)
ENGINE=InnoDB
;
组合键示例:
结果
foo_id
索引因冗余而被删除。由于
foo\u id
是复合键中的第一列,因此隐式foo\u id
索引FK\u BAR\u foo
将被删除
CREATE TABLE `BAR` (
`id` INT(11) NOT NULL,
`foo_id` INT(11) NOT NULL,
`b` INT(11) NOT NULL,
PRIMARY KEY (`id`),
UNIQUE INDEX `foo_id_b` (`foo_id`, `b`),
CONSTRAINT `FK_BAR_FOO` FOREIGN KEY (`foo_id`) REFERENCES `FOO` (`id`) ON DELETE CASCADE
)
ENGINE=InnoDB
;
明确的关键示例:
如果使用满足外键约束的显式索引创建表,MySQL将忽略冗余索引
DROP TABLE IF EXISTS `BAR`;
DROP TABLE IF EXISTS `FOO`;
CREATE TABLE `FOO` (
`id` INT(11) NOT NULL,
PRIMARY KEY (`id`)
)
ENGINE=InnoDB
;
CREATE TABLE `BAR` (
`id` INT(11) NOT NULL,
`foo_id` INT(11) NOT NULL,
`b` INT(11) NOT NULL,
PRIMARY KEY (`id`),
INDEX `FK_BAR_FOO` (`foo_id`),
CONSTRAINT `FK_BAR_FOO` FOREIGN KEY (`foo_id`) REFERENCES `FOO` (`id`) ON DELETE CASCADE
)
ENGINE=InnoDB
;
ALTER TABLE `BAR`
ADD UNIQUE INDEX `foo_id_b` (`foo_id`, `b`);
SHOW CREATE TABLE `BAR`;
结果
创建了foo\u id、b
的复合键索引和foo\u id
上的索引
CREATE TABLE `BAR` (
`id` INT(11) NOT NULL,
`foo_id` INT(11) NOT NULL,
`b` INT(11) NOT NULL,
PRIMARY KEY (`id`),
UNIQUE INDEX `foo_id_b` (`foo_id`, `b`),
INDEX `FK_BAR_FOO` (`foo_id`),
CONSTRAINT `FK_BAR_FOO` FOREIGN KEY (`foo_id`) REFERENCES `FOO` (`id`) ON DELETE CASCADE
)
ENGINE=InnoDB
;
解决方案 在脚本中,在尝试删除/添加索引之前,请验证索引(不存在)
IF NOT EXISTS(
SELECT 1 FROM INFORMATION_SCHEMA.STATISTICS
WHERE TABLE_NAME = 'cfgAttributeInstances'
AND INDEX_NAME = 'new_nodeComponentID'
AND INDEX_SCHEMA = 'DbName')
THEN
ALTER TABLE `cfgAttributeInstances`
ADD UNIQUE INDEX `new_nodeComponentID` (`nodeComponentID`,`attributeID`);
END IF;
IF EXISTS (
SELECT 1 FROM INFORMATION_SCHEMA.STATISTICS
WHERE TABLE_NAME = 'cfgAttributeInstances'
AND INDEX_NAME = 'nodeComponentID'
AND INDEX_SCHEMA = 'DbName')
THEN
ALTER TABLE `cfgAttributeInstances`
DROP INDEX `nodeComponentID`;
END IF;
谢谢你的回答。我不明白的是:为什么在一个
mysqldump
/restore周期后,我们不能重现这种情况?为什么db1和db2的行为与最初的问题不同?@PeterV.Mørch至于为什么db1和db2的工作方式不同,这是因为表模式可能被转储到了一个服务器上,如我的第二个示例所示。按照我在第一个示例中执行的顺序发出查询,将在db1和db2服务器上执行相同的操作,就像在db FIDLE上一样。除非它们是不支持冗余索引删除的不同mysql版本。@PeterV.Mørch找到了文档参考,并使用链接和引号进行了更新。
CREATE TABLE `BAR` (
`id` INT(11) NOT NULL,
`foo_id` INT(11) NOT NULL,
`b` INT(11) NOT NULL,
PRIMARY KEY (`id`),
UNIQUE INDEX `foo_id_b` (`foo_id`, `b`),
INDEX `FK_BAR_FOO` (`foo_id`),
CONSTRAINT `FK_BAR_FOO` FOREIGN KEY (`foo_id`) REFERENCES `FOO` (`id`) ON DELETE CASCADE
)
ENGINE=InnoDB
;
IF NOT EXISTS(
SELECT 1 FROM INFORMATION_SCHEMA.STATISTICS
WHERE TABLE_NAME = 'cfgAttributeInstances'
AND INDEX_NAME = 'new_nodeComponentID'
AND INDEX_SCHEMA = 'DbName')
THEN
ALTER TABLE `cfgAttributeInstances`
ADD UNIQUE INDEX `new_nodeComponentID` (`nodeComponentID`,`attributeID`);
END IF;
IF EXISTS (
SELECT 1 FROM INFORMATION_SCHEMA.STATISTICS
WHERE TABLE_NAME = 'cfgAttributeInstances'
AND INDEX_NAME = 'nodeComponentID'
AND INDEX_SCHEMA = 'DbName')
THEN
ALTER TABLE `cfgAttributeInstances`
DROP INDEX `nodeComponentID`;
END IF;