自动递增主要在计数中留下空白

时间:2013-05-16 08:38:37

标签: mysql primary-key

我有一张带有自动增量主键的表。此表用于存储数百万条记录,我现在不需要删除任何内容。问题是,当插入新行时,由于某些错误,自动增量键在自动增量ID中留下一些空隙。例如,在5之后,下一个id为8,留下6和7的间隙结果是,当我计算行数时,结果为28000,但最大ID为58000.可能是什么原因?我没有删除任何东西。我该如何解决这个问题。

P.S。我在插入记录时使用insert ignore,以便在我尝试在唯一列中插入重复条目时不会出错。

5 个答案:

答案 0 :(得分:12)

这是设计上的,并且将永远发生。

为什么?

让我们做两个正在进行INSERT的重叠事务

  • 事务1执行INSERT,获取值(假设为42),执行更多工作
  • 事务2执行INSERT,获取值43,执行更多工作

然后

  • 交易1失败。回滚。 42未使用
  • 交易2以43
  • 完成

如果保证连续值,则每个交易必须一个接一个地发生。不太可扩展。

另见Do Inserted Records Always Receive Contiguous Identity Values(SQL Server但适用相同的原则)

答案 1 :(得分:3)

您可以创建一个触发器来处理自动增量:

CREATE DEFINER=`root`@`localhost` TRIGGER `mytable_before_insert` BEFORE INSERT ON `mytable` FOR EACH ROW 
BEGIN
  SET NEW.id = (SELECT IFNULL(MAX(id), 0) + 1 FROM mytable);;
END

答案 2 :(得分:2)

这是mySQL的存储引擎InnoDB中的一个问题。

确实不是问题

检查文档时 http://dev.mysql.com/doc/refman/5.0/en/innodb-auto-increment-handling.html

它基本上说InnoDB使用特殊的表来启动时自动增量

它使用的查询类似于

SELECT MAX(ai_col) FROM t FOR UPDATE;

这样可以提高并发性,而不会对数据产生任何影响。

没有使用MyISAM而不是InnoDB作为存储引擎

答案 3 :(得分:1)

也许(我没有对此进行测试)解决方案是将innodb_autoinc_lock_mode设置为0。 根据{{​​3}},这可能会使事情变得更慢(如果在单个查询中执行多行插入),但应该删除间隙。

答案 4 :(得分:1)

您可以尝试插入:

insert ignore into table select (select max(id)+1 from table), "value1", "value2" ;

这将尝试

  • 插入具有最后一个未使用的ID(不是自动递增)的新数据
  • 如果在唯一字段中发现重复条目​​,请忽略它
  • 否则将正常插入新数据

    (但是如果找到重复的条目,此方法不支持更新字段)