MySql upsert和自动增量导致间隙

发布于 2024-09-18 02:10:46 字数 244 浏览 6 评论 0原文

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

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

I've got a MySql table with an auto-increment primary key, and it seems that all of the various upsert methods (INSERT IGNORE and ON DUPLICATE KEY UPDATE) suffer from the, uh, feature that the auto-increment field increments, even if a row is updated and not inserted. This means that gaps are introduced into the table, which I find undesirable.

So the question is: is there any way to upsert records in a table with an auto-increment field without auto-incrementing that field, if the upsert in fact merely updates the row. To my mind, this is the way upsert should behave, but it doesn't seem to.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

沉鱼一梦 2024-09-25 02:10:46

这个“问题”仅存在于InnoDB中。

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

来自 文档

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

从 t 中选择 MAX(ai_col) 进行更新;

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

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


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

This "problem" is only in InnoDB.

It is by design, and intended to improve concurrency: another thread can use an AUTO_INCREMENT without having to wait for the results of an UPSERT operation.

From the docs:

After a server startup, for the first insert into a table t, InnoDB executes the equivalent of this statement:

SELECT MAX(ai_col) FROM t FOR UPDATE;

InnoDB initializes but does not increment the value and stores it for use by later inserts

When accessing the auto-increment counter, InnoDB uses a special table-level AUTO-INC lock that it keeps to the end of the current SQL statement, not to the end of the transaction. The special lock release strategy was introduced to improve concurrency for inserts into a table containing an AUTO_INCREMENT column. Nevertheless, two transactions cannot have the AUTO-INC lock on the same table simultaneously, which can have a performance impact if the AUTO-INC lock is held for a long time. That might be the case for a statement such as INSERT INTO t1 ... SELECT ... FROM t2 that inserts all rows from one table into another.

MyISAM does not exhibit this behavior, since it's AUTO_INCREMENT algorithm is implemented differently (due to its limited ability to support concurrent DML).

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文