2014-09-02 60 views
2

我将与mysql一起工作。我有一些主键作为整数自动递增(称为ID)的表。关于mysql插入时自动增加行为

当我插入一些无法插入的东西(例如,一个独特的字段IP,并插入相同的IP)它不会让你插入(这是好的!)但是,然后,ID增加......是不正确的,因为我试图插入,但我不能。

Is this a normal behavior? 

我如何确保在插入“好的”值时只会增加id?

谢谢

+0

自动递增的ID意味着在幕后......如果他们读取21047132123或1,应该没有关系。这是Mysql中的正常行为。不要粗言秽语,但为什么你在乎增加? – Twelfth 2014-09-02 22:50:31

+0

我只是好奇,如果这是一个正常的行为...但是,看起来我可以做一个利用(以某种方式),如果我可以插入多次溢出权? – Edwardo 2014-09-02 22:57:30

+0

这是,比尔卡尔文的答案很好解释。记住自动递增的ID从不打算作为行号,它们只是旨在是唯一的。如果你想分配一个需要顺序显示的ID,那么我会设置一个自动递增的ID列,并让它做它最擅长的事情(保持行的唯一性和连接表),第二列称为' display_ID'或某种程度并自行填充它。 – Twelfth 2014-09-02 23:02:04

回答

4

是的,这是正常的行为。自MySQL 5.1以来,InnoDB尽快释放表的auto-inc锁,以允许并发线程在不等待线程的情况下执行自己的插入操作。这意味着在INSERT成功之前释放自动锁定。所以如果INSERT出了问题,它不能“返回”自动递增的值,因为另一个线程可能已经分配了第N + 1个自动增量值,并且InnoDB不跟踪除最近的自动增量-inc值。

如果您有很多失败的插入,这会导致在某些情况下很多auto-inc值会“丢失”。例如,我帮助一个站点一直运行到最大有符号的INT值(2 -1),因为它们为成功插入的每一行跳过了1000-1500个值。所有这些都是因为其用户名列上存在次要的唯一约束。

通过在my.cnf配置文件中设置innodb_auto_inc_lock_mode=0,您可以使InnoDB的行为与MySQL 5.0中的行为相似,让自动递增值返回其在INSERT失败时的增量。 阅读http://dev.mysql.com/doc/refman/5.6/en/innodb-auto-increment-configurable.html了解更多详情。

但请注意,这限制了并发性,因为线程插入将会使auto-inc保持更长的时间。其他线程必须等待当前插入的线程完全成功,然后才能获取自动更新锁定。如果您对同一张表的并发插入率很高,则可能会降低您的应用速度。

此外,主键序列中存在间隙是正常的,因为无论如何有些事务会回滚,否则行会被删除。永远不要假设你的主键值将会完全连续。它们旨在成为唯一的值,而不是行号。

+0

谢谢!顺便说一句,你是否以这种方式解决了问题公司? – Edwardo 2014-09-03 00:08:56

+0

我告诉他们这个选项,但他们宁愿不牺牲可扩展性。该选项会改变* all *表的锁定行为,而不仅仅是他们遇到的问题。他们最终选择在尝试INSERT之前选择有冲突用户名的表。这是一个竞争条件,因为另一个会话可能会潜入并在SELECT和INSERT之间插入冲突的用户名。但它减少了丢失身份证的数量。 – 2014-09-03 16:17:08