我们有一个自动递增字段设置为INT(11)的MySQL表。 这张表几乎存储了在应用程序中运行的作业列表。 在应用程序生命周期的任何时刻,表格可能包含数千个条目或完全空白(即所有内容都已完成)。
这个领域不是外键的。
自动增量似乎随机将其自身重置为零,虽然我们从来没有真正能够陷入重置。
这个问题变得很明显,因为我们看到自动增量字段达到了60万条logging,然后一段时间后自动增量字段似乎在低于1000的条件下运行。
这几乎就像自动增量自动重置,如果表是空的。
这是可能的,如果是的话,我该如何关掉它或改变它重置的方式?
如果不是,有没有人有解释为什么它可能会这样做?
谢谢!
自动递增计数器仅存储在主存储器中,而不是存储在磁盘上。
http://dev.mysql.com/doc/refman/4.1/en/innodb-auto-increment-handling.html
因此,服务(或服务器)重新启动时,将发生以下情况:
在服务器启动后,对于第一次插入表t,InnoDB执行相当于下面的语句:SELECT MAX(ai_col)FROM t FOR UPDATE;
InnoDB将由语句检索的值递增1,并将其分配给表中的列和自动递增计数器。 如果表是空的,InnoDB使用值1。
所以用简单的英文,MySQL服务启动后,不知道你的表的自动增量值应该是什么。 所以,当你第一次插入一行时,它会查找使用自动增量的字段的最大值,将该值加1,并使用结果值。 如果没有行,它将从1开始。
这对我们来说是一个问题,因为我们使用表和mysql的自动递增function在multithreading环境中整齐地pipe理ID,用户被redirect到第三方支付站点。 因此,我们必须确保第三方得到并返回给我们的身份证是独一无二的,并保持这种方式(当然,用户在redirect后可能会取消交易)。
因此,我们创build了一个行,获取生成的自动增量值,删除行以保持表格清洁,并将值转发到付款站点。 我们最终做了什么来解决InnoDB处理AI值的问题如下:
$query = "INSERT INTO transactions_counter () VALUES ();"; mysql_query($query); $transactionId = mysql_insert_id(); $previousId = $transactionId - 1; $query = "DELETE FROM transactions_counter WHERE transactionId='$previousId';"; mysql_query($query);
这始终将最新的transactionId作为表格中的一行生成,而不会不必要地炸掉表格。
希望能帮助其他任何可能遇到这个问题的人。
-Gremio
在黑暗中只是一个镜头 – 如果应用程序正在使用TRUNCATE TABLE来清空表格,那么它将重置自动递增字段。 这里是对这个问题的简要讨论 。 虽然这个链接提到InnoDB不重置trunc上的auto_increments,但是这被报告为一个bug并且在几年前被修复。
假设我的猜测是正确的,你可以从截断到删除来解决问题。
我们遇到过这个问题,并发现当优化表运行在一个空表上时,自动增量值也被重置。 看到这个MySQL错误报告 。
作为解决方法,您可以执行以下操作:
ALTER TABLE a AUTO_INCREMENT=3 ENGINE=innoDB;
而不是OPTIMIZE TABLE 。
看起来这是MySQL在内部做的(显然没有设置自动增量值)
只有该值的显式重置,或该字段的删除/重新创build,或其他类似的暴力操作才能重置auto_increment计数器。 (TRUNCATE是一个非常好的理论。)当你所看到的最后一个值只有600k时,你似乎不可能突然包装一个32位的INT。 这绝对不应该因为桌面空置而重置。 你在PHP代码中有一个mysql错误或者其他东西。 或者隔壁房间里的人正在玩弄你。
你可以打开二进制日志进行debugging,因为它将包含像这样的声明:
SET INSERT_ID=3747670/*!*/;
那么至less你可以看到该表发生的每一个细节,包括在计数器重置之前。
ALTER TABLE table_name ENGINE = MyISAM
为我工作。 我们的表总是保持非常小,所以不需要InnoDB。