MySql upsert 和自动增量导致间隙

Jos*_*ank 6 mysql upsert

我有一个带有自动增量主键的 MySql 表,似乎所有各种 upsert 方法(INSERT IGNORE 和 ON DUPLICATE KEY UPDATE)都受到自动增量字段增量的影响,甚至如果一行被更新但没有插入。这意味着在表格中引入了间隙,我认为这是不可取的。

所以问题是:如果 upsert 实际上只是更新行,是否有任何方法可以在具有自动递增字段的表中更新记录而不自动递增该字段。在我看来,这是 upsert 应该表现的方式,但似乎并非如此。

Qua*_*noi 5

这个“问题”仅在InnoDB.

它是设计使然,旨在提高并发性:另一个线程可以使用 ,AUTO_INCREMENT而无需等待UPSERT操作的结果。

文档

服务器启动后,对于第一次插入表tInnoDB执行此语句的等效项:

SELECT MAX(ai_col) FROM t FOR UPDATE;
Run Code Online (Sandbox Code Playgroud)

InnoDB 初始化但不增加值并存储它以供以后插入使用

当访问自动递增计数器时,InnoDB使用一个特殊的表级AUTO-INC锁,它一直保持到当前SQL语句的末尾,而不是事务的末尾。引入了特殊的锁释放策略以提高插入到包含AUTO_INCREMENT列的表的并发性。然而,两个事务不能AUTO-INC同时在同一个表上拥有锁,如果AUTO-INC长时间持有锁,这会对性能产生影响。对于诸如INSERT INTO t1 ... SELECT ... FROM t2将一个表中的所有行插入到另一个表中的语句来说,可能就是这种情况。

MyISAM不会表现出这种行为,因为它的AUTO_INCREMENT算法实现方式不同(由于其支持 concurrent 的能力有限DML)。