2

我试图了解 innodb 关于重用可能出现在 AUTO_INCREMENT 值序列中的间隙的确切行为。问题是在我看来,我在文档中发现了两个相互矛盾的描述。

  1. http://dev.mysql.com/doc/refman/5.6/en/innodb-auto-increment-configurable.html

在所有锁定模式(0、1 和 2)中,如果生成自增值的事务回滚,则这些自增值将“丢失”。一旦为自增列生成了值,无论“INSERT-like”语句是否完成,以及包含的事务是否回滚,都无法回滚。这种丢失的值不会被重用。

2. http://dev.mysql.com/doc/refman/5.6/en/innodb-restrictions.html

当您重新启动 MySQL 服务器时,InnoDB 可能会重用为 AUTO_INCREMENT 列生成但从未存储的旧值(即,在回滚的旧事务期间生成的值)。

那么这些丢失的值会被重用吗?如果在重新启动 MYSQL 服务器后它们确实会被重用,那么考虑到 InnoDB 通过执行等效的语句来确定新的 AUTO_INCREMENT 值怎么可能?

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

?

4

2 回答 2

1

第一种情况是正常行为和您所期望的。

第二个案例是一个奇怪的案例。

假设我们正在为写入分配 1024,但写入或事务未完成,因为 MySQL 已停止或崩溃。在某些情况下,会记录 1024 的使用情况,因此接下来将分配 1025。但是有一个小窗口,启动表中没有记录1024的分配。这解释了案例 2。

此外,InnoDB 实际上并没有为新分配做一个真正的 MAX(但 MyISAM 做)。它是等价的。它确实在启动时做到了

还看到这些

更新。

问题中的第一个链接(http://dev.mysql.com/doc/refman/5.6/en/innodb-auto-increment-traditional.html)解释了这种行为。如果链接失效,请在下面选择引号:

如果您为 InnoDB 表指定 AUTO_INCREMENT 列,则 InnoDB 数据字典中的表句柄包含一个称为自动增量计数器的特殊计数器,用于为该列分配新值。此计数器仅存储在主存储器中,而不存储在磁盘上

因此,这是一个运行时的事情,其中​​数字与实际表分开递增。这解释了差距:新值的分配与写入不同。

InnoDB 使用以下算法为包含名为 ai_col 的 AUTO_INCREMENT 列的表 t 初始化自动增量计数器:在服务器启动后,对于表 t 的第一次插入,InnoDB 执行此语句的等效项:

因此,由于服务器重新启动而导致分配成功但写入失败的文件将被丢弃。

于 2013-05-23T08:25:58.037 回答
0

我相信这意味着

如果生成自动增量值的事务回滚,则这些自动增量值将“丢失” ,除非在需要生成任何进一步的自动增量值之前重新启动服务器

我找不到确认此行为的权威参考,但以下测试似乎同意:

bash > mysql test

mysql > CREATE TABLE ai (id INT AUTO_INCREMENT PRIMARY KEY);
mysql > BEGIN;
mysql > INSERT INTO ai VALUES (NULL);
mysql > ROLLBACK;
mysql > BEGIN;
mysql > INSERT INTO ai VALUES (NULL);
mysql > COMMIT;
mysql > SELECT * FROM ai;
+----+
| id |
+----+
|  2 |
+----+
mysql > BEGIN;
mysql > INSERT INTO ai VALUES (NULL);
mysql > ROLLBACK;
mysql > -- expecting auto-increment value "3" to be "consumed"
mysql > quit;

bash > service mysql restart
bash > mysql test

mysql > BEGIN;
mysql > INSERT INTO ai VALUES (NULL);
mysql > COMMIT;
mysql > SELECT * FROM ai;
+----+
| id |
+----+
|  2 |
|  3 |
+----+
于 2013-05-23T08:24:48.737 回答