我编写了一个访问MySQL innodb数据库的java程序。
每当INSERT IGNORE语句遇到重复条目时,Auto Increment主键就会递增。
这种行为是预期的吗?我认为IGNORE不应该发生这种情况。这意味着IGNORE实际上会产生额外的开销来写入新的主键值。
表格如下:
CREATE TABLE `tablename` (
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
`rowname` varchar(50) NOT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `rowname` (`rowname`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
谢谢!
答案 0 :(得分:31)
这是自MySQL 5.1.22以来的默认行为。
您可以将配置变量innodb_autoinc_lock_mode
设置为0
(a.k.a“传统”锁定模式)如果您想避免自动增量列中的间隙。但是,它可能会导致性能下降,因为此模式具有在INSERT
完成之前保持表锁定的效果。
来自InnoDB AUTO_INCREMENT Lock Modes上的文档:
innodb_autoinc_lock_mode = 0
(“传统”锁定模式)传统的锁定模式提供了与之相同的行为 在
innodb_autoinc_lock_mode
配置参数之前 在MySQL 5.1中引入。提供传统的锁定模式选项 用于向后兼容性,性能测试和解决方案 “混合模式插入”的问题,由于可能存在差异 语义。在这种锁定模式下,所有“INSERT-like”语句都会获得一个特殊的声明 表级
AUTO-INC
锁定,用于插入AUTO_INCREMENT
的表 列。此锁定通常持有到语句的末尾(不是 到交易结束时)确保自动增加值 按给定的可预测和可重复的顺序分配INSERT
语句的序列,并确保自动递增 任何给定语句分配的值都是连续的。
答案 1 :(得分:10)
答案 2 :(得分:1)
我认为这种行为是合理的。不应依赖自动增量来给出没有间隙的序列。
例如,回滚事务仍然使用ID:
INSERT INTO t (normalcol, uniquecol) VALUES
('hello','uni1'),
('hello','uni2'),
('hello','uni1');
显然会生成唯一的密钥违规,并且不会在数据库中插入任何行(假设此处为事务引擎)。但是,它可能会消耗多达3个auto-inc值而不插入任何内容。
答案 3 :(得分:-2)
不确定是否预期,但我建议切换到:
INSERT ... ON DUPLICATE KEY UPDATE