17

当使用 MySQL START TRANSACTION 并且 MySQL 决定回滚时 - 如果表具有 AUTO_INCREMENT 列 - 在回滚期间该列是否会减少?

还是应该?

我遇到了一些事务数据被正确回滚的问题——但看起来该表是自动递增的,而不是在回滚中递减。


# BOTH TABLES START OUT EMPTY // TABLE1 ID is **auto_increment** 

START TRANSACTION;

INSERT INTO `TABLE1` (`ID` ,`NAME`) VALUES (NULL , 'Ted');  # MySQL TABLE1 **ID** is Auto incremented to 1 

INSERT INTO `TABLE2` (`ID` ,`WRONGVALUE`) VALUES (NULL , 'some value');  # error. This TRANSACTION will not succeed 

COMMIT;  # Because of the error - this TRANSACTION is now rolled back and Ted is NOT added


因为 MySQL 将自动增加第一个表上的 ID - 无论事务是成功还是失败 - 这是自己减少表的标准做法吗?

4

2 回答 2

48

不,自动增量机制必须在事务范围之外工作,因为在您完成事务之前,另一个用户可能正在插入同一个表。其他用户的交易必须能够分配下一个值,才知道你的交易是否在使用你刚刚分配的值。

回复您的评论:如果我可以说得更清楚一点,事务范围的任何更改都可能被回滚。自增计数器不会回滚,因此它不服从事务的原子性。它也不服从隔离,因为即使您的事务尚未提交,另一个事务也会获得下一个值。

自动增量的工作方式意味着有时,如果您插入一些行然后回滚您的事务,您使用自动增量分配的值将永远丢失!

但这没关系。主键值必须是唯一的,但它们不需要是连续的。换句话说,它们不是行号,你不应该那样使用它们。因此,您永远不需要减少自动增量创建的值。

于 2013-02-07T18:49:47.663 回答
1

披露:我对 SQL 比较陌生,所以其中一些可能是错误的。但这就是我的理解。自动增量必须在事务之外起作用,否则您可能会危及数据。假设您有 2 个用户都试图连接到您的分贝。两者都在创建帐户。创建帐户 1 时,它会递增到 1。然后创建帐户 2 并递增到 2。到目前为止,它看起来如下所示:

  • (1、账户1)
  • (2、账户2)
  • 增量:2。

现在让我们假设账户 2 提交,但账户 1 失败。现在您的表格如下所示:

  • (2、账户2)
  • 增量:1。

因为您减少了自动增量,所以当有人尝试注册新帐户时,您将无法获得唯一值,因为这对将是:

  • (2,账户2)
  • 尝试插入 (2, NewAccount)

这将失败,因为主键 2 不是唯一的。

如果您需要修复您的表(出于开发目的),您始终可以运行以下代码:

ALTER TABLE `DB_NAME`.`TABLE_NAME` 
AUTO_INCREMENT = 1 (or some other number);
于 2019-09-14T22:09:49.440 回答