MySql upsert和自动增量会导致间隙
我有一个带有自动递增主键的MySql表,所有的upsert方法(INSERT IGNORE和ON DUPLICATE key UPDATE)都有自动递增字段递增的特性,即使一行被更新并且没有插入。这意味着在表中引入了间隙,这是我不希望看到的 所以问题是:如果upsert实际上只是更新行,那么有没有办法在具有自动递增字段的表中upsert记录而不自动递增该字段。在我看来,这是upsert应该采取的行为方式,但似乎不是这样。这个“问题”只存在于MySql upsert和自动增量会导致间隙,mysql,upsert,Mysql,Upsert,我有一个带有自动递增主键的MySql表,所有的upsert方法(INSERT IGNORE和ON DUPLICATE key UPDATE)都有自动递增字段递增的特性,即使一行被更新并且没有插入。这意味着在表中引入了间隙,这是我不希望看到的 所以问题是:如果upsert实际上只是更新行,那么有没有办法在具有自动递增字段的表中upsert记录而不自动递增该字段。在我看来,这是upsert应该采取的行为方式,但似乎不是这样。这个“问题”只存在于InnoDB中 它是经过设计的,旨在提高并发性:另一个线
InnoDB
中
它是经过设计的,旨在提高并发性:另一个线程可以使用自动增量
,而不必等待上传
操作的结果
从:
服务器启动后,对于表t
中的第一次插入,InnoDB
执行与此语句等效的语句:
SELECT MAX(ai_col) FROM t FOR UPDATE;
…
InnoDB
初始化但不增加值,并存储该值以供以后的插入使用
…
当访问自动递增计数器时,InnoDB
使用一个特殊的表级auto-INC
锁,它将锁保持在当前SQL
语句的末尾,而不是事务的末尾。引入了特殊的锁释放策略,以提高插入到包含自动增量
列的表中的并发性。但是,两个事务不能同时在同一个表上具有AUTO-INC
锁,如果长时间保持AUTO-INC
锁,这可能会对性能产生影响。这可能是语句的情况,例如INSERT INTO t1。。。选择。。。从t2
将一个表中的所有行插入到另一个表中
MyISAM
没有表现出这种行为,因为它的AUTO_INCREMENT
算法的实现方式不同(因为它支持并发DML
的能力有限)。我发现您对这些差距的担忧更不可取。一点也不必担心汽车消费数量。您可能误解了它的概念。我理解实际值是没有意义的,但如果浪费太多,可能会耗尽空间,需要转到更大的数据类型,然后所有行将占用更多的空间。此外,我发现差距不明显,尽管我认为这不是最大的问题。MySQL
支持SERIAL
类型,它是BIGINT UNSIGNED not NULL AUTO_INCREMENT UNIQUE
的别名BIGINT
最多可保存值18446744073709551615
。我给读者留下一个很好的比喻比较(比如,与宇宙时代等),作为练习。而且它也只有8
字节。虽然使用额外的4字节看起来很浪费,但我想在大多数应用程序中这并不是什么大问题。我写了一个innodb gap答案,感谢您提供了有关此行为的详细信息。我会接受这个答案,但我还是想知道是否有高性能的方法可以在没有间隙的情况下完成upsert。@Joshua:您可以创建一个单字段、单记录的“序列”表,并在触发器中更新它。但是,这会严重影响表的并发性。@Quassnoi:我正在运行MyISAM,得到了相同的结果problem@hornetbzz:请将其作为另一个问题发布。@Quassnoi:我不认为这个问题与Innodb没有严格的关系,因为我解决了我的问题,只是在关键字段上添加了一个唯一的约束(取消AI字段的链接)。因为我猜你是法国人,你会知道怎么做的