MySQL 在 TRANSACTION、COMMIT 和 ROLLBACK 上自动增加列
Posted
技术标签:
【中文标题】MySQL 在 TRANSACTION、COMMIT 和 ROLLBACK 上自动增加列【英文标题】:MySQL Auto Increment Columns on TRANSACTION, COMMIT, and ROLLBACK 【发布时间】:2013-01-23 09:29:55 【问题描述】:当使用 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 - 无论事务是成功还是失败 - 这是标准做法自己递减表吗?
【问题讨论】:
我相信自增一涨就回不来了 据我所知,事务不可能部分完成......要么完全完成,要么完全回滚(这是事务的重点)......除此之外,我同意与 jcho360 【参考方案1】:不,自动增量机制必须在事务范围之外工作,因为在您完成事务之前,另一个用户可能正在向同一个表中插入数据。其他用户的交易必须能够分配下一个值,才能知道你的交易是否在使用你刚刚分配的值。
关于您的评论:如果我可以说得更清楚,事务范围的任何更改都可能被回滚。自增计数器不会回滚,因此它不遵守事务的原子性。它也不遵守隔离,因为即使您的事务尚未提交,另一个事务也会获得下一个值。
自动增量的工作方式意味着有时,如果您插入一些行然后回滚事务,您使用自动增量分配的值将永远丢失!
但这没关系。主键值必须是唯一的,但它们不需要是连续的。换句话说,它们不是行号,你不应该那样使用它们。因此,您永远不需要递减由自动增量创建的值。
【讨论】:
+1 很好的答案...我知道自动增量在事务范围之外起作用,但我从未与并发所需的内容建立联系。 @Bill Karwin 嘿,比尔?我只是想问一下您是否认为我在问题“#因为错误-此事务现在已回滚并且未添加 Ted”中的措辞是正确的-这样说准确吗-或者实际上是“回滚”-或者它甚至继续前进......我想我想说的是 - 回滚一词是说表中的部分数据被临时更改......然后“回滚”就像在临时数据被删除了? @KDawg,是的,InnoDB 记录并存储所有更改,如果是更新或删除,旧行的副本也会被保留。如果您回滚,则会丢弃新版本并恢复原始版本。这作为一种垃圾收集在后台异步发生(也就是说,它可能在几分钟甚至几小时后发生)。甚至在此之前,InnoDB 就可以透明地返回您查询的任何行的正确版本。 我看到的缺点是,在开发/测试环境中,您可以非常快速地达到 tinyint id。 @RafaelBarros,没错,对于大多数表来说,tinyint 的范围通常太小。但这与自增的隔离无关。【参考方案2】:披露:我对 SQL 比较陌生,所以其中一些可能是错误的。但这就是我的理解。 自动增量必须在事务之外起作用,否则您可能会危及数据。假设您有 2 个用户都试图连接到您的分贝。两者都在创建帐户。创建帐户 1 时,它会递增到 1。然后创建帐户 2 并递增到 2。到目前为止,它看起来如下所示:
(1,帐户 1) (2,帐户2) 增量:2。现在让我们假设帐户 2 提交,但帐户 1 失败。现在您的表格如下所示:
(2,帐户2) 增量:1。因为您减少了自动增量,所以当有人尝试注册新帐户时,您将无法获得唯一值,因为这对将是:
(2,Account2) 正在尝试插入 (2, NewAccount)这会失败,因为主键 2 不是唯一的。
如果您需要修复表(出于开发目的),您可以随时运行以下代码:
ALTER TABLE `DB_NAME`.`TABLE_NAME`
AUTO_INCREMENT = 1 (or some other number);
【讨论】:
以上是关于MySQL 在 TRANSACTION、COMMIT 和 ROLLBACK 上自动增加列的主要内容,如果未能解决你的问题,请参考以下文章
MySQL事务(transaction) (有这篇就足够了..)
MySQL--当mysqldump --single-transaction遇到alter table
MySQL ------ 事务处理(transaction)(二十八)