Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/mysql/57.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/fortran/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
MySql upsert和自动增量会导致间隙_Mysql_Upsert - Fatal编程技术网

MySql upsert和自动增量会导致间隙

MySql upsert和自动增量会导致间隙,mysql,upsert,Mysql,Upsert,我有一个带有自动递增主键的MySql表,所有的upsert方法(INSERT IGNORE和ON DUPLICATE key UPDATE)都有自动递增字段递增的特性,即使一行被更新并且没有插入。这意味着在表中引入了间隙,这是我不希望看到的 所以问题是:如果upsert实际上只是更新行,那么有没有办法在具有自动递增字段的表中upsert记录而不自动递增该字段。在我看来,这是upsert应该采取的行为方式,但似乎不是这样。这个“问题”只存在于InnoDB中 它是经过设计的,旨在提高并发性:另一个线

我有一个带有自动递增主键的MySql表,所有的upsert方法(INSERT IGNORE和ON DUPLICATE key UPDATE)都有自动递增字段递增的特性,即使一行被更新并且没有插入。这意味着在表中引入了间隙,这是我不希望看到的

所以问题是:如果upsert实际上只是更新行,那么有没有办法在具有自动递增字段的表中upsert记录而不自动递增该字段。在我看来,这是upsert应该采取的行为方式,但似乎不是这样。

这个“问题”只存在于
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字段的链接)。因为我猜你是法国人,你会知道怎么做的