下面的场景是否可能?
MySQL 版本 5.6.15
CREATE TABLE my_table (
id int NOT NULL AUTO_INCREMENT.
data1 int,
data2 timestamp,
PRIMARY KEY (id)
) ENGINE=InnoDB;
innodb_autoinc_lock_mode = 1
AUTO_INCREMENT=101
- 0 毫秒:查询 A 运行:
INSERT INTO my_table (data1, data2) VALUES (101, FROM_TIMESTAMP(1418501101)), (102, FROM_TIMESTAMP(1418501102)),
.. [200 个值总计] ..,(300, FROM_TIMESTAMP(1418501300));
- 500 毫秒:运行查询 B:
INSERT INTO my_table (data1, data2) VALUES (301, FROM_TIMESTAMP(1418501301));
- 505 毫秒:查询 B 已完成。该行获取 id=301。
- 1000 毫秒:
SELECT id FROM my_table WHERE id >= 300;
— 将返回一行 (id=301)。 - 1200 毫秒:查询 A 完成。行从 id=101 到 id=300。
- 1500 毫秒:
SELECT id FROM my_table WHERE id >= 300;
— 将返回两行 (id=300, id=301)。
换句话说,id=301的行有没有可能比id=300的行先被选中?
如果可能的话,如何避免呢?
最佳答案
为什么查询 A 的运行时间超过一秒?呸!是的,您所看到的正是我所期望的行为方式。
插入新行时会立即保留主键 101 到 300。这需要几毫秒。然后,它花费超过 1 秒的时间重建索引,在完成所有这些操作的一半时,您运行了另一个插入新行的查询,使用下一个可用的 auto_increment: 301。
正如 Alin Purcaru 所说,您可以通过更改锁定模式来避免此特定问题,但这会导致性能问题(查询 B 将花费 700 毫秒执行而不是 5 毫秒执行。
在高负载情况下,问题会呈指数级恶化,您最终会看到“连接过多”错误,从而有效地使整个数据库脱机。
还有其他罕见的情况,auto_increment 会给出“无序”的增量,这不会通过锁定来解决。
我个人认为最好的选择是使用 UUID 而不是 auto_increment 作为主键,然后有一个时间戳列(作为带有微秒的 double )来确定将哪些顺序行插入到数据库中。
关于mysql - 具有较大自动增量值的行是否可以比具有较小自动增量值的行出现得更快?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27463580/