我有一个带有自动增量主键的表。该表旨在存储数百万条记录,我现在不需要删除任何内容。问题是,当插入新行时,由于某些错误,自动增量键在自动增量 id 中留下了一些间隙。例如,在 5 之后,下一个 id 是 8,留下 6 和 7 的间隙.结果是当我计算行数时,结果为28000,但最大id为58000。可能是什么原因?我没有删除任何东西。我该如何解决这个问题。
PS我在插入记录时使用insert ignore,这样当我尝试在唯一列中插入重复条目时它不会出错。
我有一个带有自动增量主键的表。该表旨在存储数百万条记录,我现在不需要删除任何内容。问题是,当插入新行时,由于某些错误,自动增量键在自动增量 id 中留下了一些间隙。例如,在 5 之后,下一个 id 是 8,留下 6 和 7 的间隙.结果是当我计算行数时,结果为28000,但最大id为58000。可能是什么原因?我没有删除任何东西。我该如何解决这个问题。
PS我在插入记录时使用insert ignore,这样当我尝试在唯一列中插入重复条目时它不会出错。
这是设计使然,并且总会发生。
为什么?
让我们采取 2 个正在执行 INSERT 的重叠事务
然后
如果保证连续值,则每笔交易都必须一个接一个地发生。不是很可扩展。
另请参阅是否插入的记录总是接收连续的标识值(SQL Server 但同样的原则适用)
这是 MySQL 的存储引擎 InnoDB 中的一个问题。
当您查看“<a href="https://dev.mysql.com/doc/refman/8.0/en/innodb-auto-increment-handling.html" rel= 上的文档时,这确实不是问题“nofollow noreferrer">AUTO_INCREMENT 在 InnoDB 中的处理”它基本上说 InnoDB 使用一个特殊的表在启动时进行自动增量
它使用的查询类似于
SELECT MAX(ai_col) FROM t FOR UPDATE;
这提高了并发性,而不会真正影响您的数据。
没有这个使用 MyISAM 而不是 InnoDB 作为存储引擎
您可以创建一个触发器来处理自动增量:
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
也许(我还没有测试过)一个解决方案是设置innodb_autoinc_lock_mode
为0
. 根据http://dev.mysql.com/doc/refman/5.7/en/innodb-auto-increment-handling.html ,这可能会使事情变慢(如果您在单个查询中执行多行插入)但是应该消除差距。
您可以尝试像这样插入:
insert ignore into table select (select max(id)+1 from table), "value1", "value2" ;
这将尝试