我尝试了解innodb关于重复使用AUTO_INCREMENT值序列中可能出现的间隙的确切行为。问题是,在我看来,我在文档中发现了两个相互矛盾的描述。
在所有锁定模式(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值,怎么可能呢?
SELECT MAX(ai_col)FROM t FOR UPDATE
答案 0 :(得分: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执行此语句的等效项: / p>
因此,由于服务器重启而成功分配但写入失败将被丢弃。
答案 1 :(得分: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 |
+----+