【问题标题】:Auto Increment skipping numbers?自动增量跳过数字?
【发布时间】:2013-07-22 22:56:30
【问题描述】:

注意:我是数据库和 PHP 新手

我有一个设置为auto incrementuniqueorder 列。

在我的 PHP 脚本中,我使用 AJAX 来获取新数据,但问题是 order 会跳过数字并且要高得多,因此迫使我在插入数据时手动更新数字。在这种情况下,我最终会将782 更改为38

$SQL = "INSERT IGNORE INTO `read`(`title`,`url`) VALUES\n ".implode( "\n,",array_reverse( $sql_values ) );

我怎样才能让它增加+1?

【问题讨论】:

  • 你能用一些示例数据发布你的数据库结构吗?
  • “自动增量”不是行索引。中止的交易和删除的记录将“消耗”进步。
  • 可能对[模拟]ROW_NUMBER 感兴趣,如果希望获得[n 个有序] 结果集的行索引。
  • @Maximus2012 很抱歉。更新了更多信息。

标签: php mysql database phpmyadmin


【解决方案1】:

如果 INSERT 失败,MySQL 5.1 及更高版本中的默认 auto_increment 行为将“丢失”自动增量值。也就是说,它每次递增 1,但如果 INSERT 失败,则不会撤消递增。丢失约 750 个值并不常见,但并非不可能(我咨询了一个站点,该站点为每个成功的 INSERT 跳过 1500 个值)。

您可以更改 innodb_autoinc_lock_mode=0 以使用 MySQL 5.0 行为并避免在某些情况下丢失值。详情请见http://dev.mysql.com/doc/refman/5.1/en/innodb-auto-increment-handling.html

要检查的另一件事是auto_increment_increment 配置变量的值。默认情况下为 1,但您可能已更改此值。同样,将其设置为高于 1 或 2 的值非常罕见,但有可能。

我同意其他评论者的观点,autoinc 列旨在是唯一的,但不一定是连续的。除非您将 autoinc 值提高得如此之快以至于您可能会超出 INT 的范围(这发生在我身上),否则您可能不应该太担心它。


您究竟是如何修复它跳过 1500 永远插入的?

INSERT 失败的原因是存在另一列具有 UNIQUE 约束,并且 INSERT 试图在该列中插入重复值。阅读我链接到的手册页,详细了解为什么这很重要。

修复方法是在尝试插入之前先执行 SELECT 以检查值是否存在。这违背了常识,即尝试插入并处理任何重复的键异常。但在这种情况下,INSERT 失败的副作用会导致 auto-inc 值丢失。执行 SELECT 首先消除了几乎所有此类异常。

但您必须处理可能的异常,即使您先选择。你仍然有竞争条件。

你是对的! innodb_autoinc_lock_mode=0 就像一个魅力。

在你的情况下,我想知道为什么这么多插入失败。我怀疑像许多 SQL 开发人员一样,您在 AJAX 处理程序中执行 INSERT 后并没有检查成功状态,因此您永远不知道其中有这么多失败。

他们可能仍然失败,您只是没有丢失 auto-inc id 作为副作用。您应该真正诊断为什么会发生如此多的失败。您可能正在生成不完整的数据,或者运行的事务比必要的多。

【讨论】:

  • You probably shouldn't worry about it so much unless you're advancing the autoinc value so rapidly - 这正是它发生的原因。我使用 AJAX 每 2 秒抓取一次新数据,增量随着我拥有的行数而增加。
  • @Bill Karwin:确实,对于更多读者来说,这只是一个无关紧要的有趣 (?) 事实 :-)
  • @zerkms,取决于有多少并发客户端正在执行此操作。 :-)
  • 你是对的! innodb_autoinc_lock_mode=0 工作就像一个魅力。
  • @Kentot,阅读我上面回答中的第二段,然后点击我参考的文档的链接。
【解决方案2】:

将 782 更改为 38 后,您可以使用 ALTER TABLE mytable AUTO_INCREMENT = 39 重置自动增量。这样你在 39 岁时继续。

但是,您应该检查为什么您的差距如此之大,并相应地更改您的设计。更改自动增加不应该是“默认”行为。

【讨论】:

  • 谢谢。相反,我进入 Operations 选项卡并更改了 auto_increment 值。
【解决方案3】:

我知道这个问题已经回答了.. 但是如果您之前删除了表中的行,mysql 会记住使用的 ID/编号,因为通常您的自动增量是唯一的..因此不会创建重复的增量..要从当前最大 ID/整数重新索引和递增,您可以执行:

ALTER TABLE TableName AUTO_INCREMENT=(SELECT max(order) + 1 FROM tablename)

【讨论】:

    【解决方案4】:

    自动递增无关紧要,如果您删除一些行 - 每次插入一行时,值都会递增。

    如果您想要一个没有间隙的编号,请不要使用自动递增,而是自己进行。你可以使用这样的东西来实现这个插入

    INSERT INTO tablename SET
        `order` = (SELECT max(`order`) + 1 FROM (SELECT * from tablename) t),
        ...
    

    如果你删除一行,你必须手动重新排列顺序列

    【讨论】:

    • 我实际上在想我可以通过使用 count() 和 PHP 来做到这一点。
    • 你可以,但我不认为,这很有效
    • 如果你想找到差距看here
    • 你试过那个 INSERT 吗?这会导致错误:You can't specify target table 'tablename' for update in FROM clause。即使它有效,如果两个线程尝试同时插入,它也容易受到竞争条件的影响。
    • 我没有@BillKarwin
    猜你喜欢
    • 2015-07-05
    • 2018-01-24
    • 2013-06-03
    • 2012-02-22
    • 2018-12-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多