Arm*_*oot 4 mysql database transactions rollback
我需要更新bigtable包含另一个表(FK 约束到oldsmalltable)的id 的表 ( )的特定列,以指向另一个表上的 ID(FK 约束到newsmalltable)。基本上这就是我在做什么:
DELIMITER //
CREATE PROCEDURE updatebigtable ()
BEGIN
DECLARE EXIT HANDLER FOR SQLEXCEPTION, SQLWARNING ROLLBACK;
START TRANSACTION;
ALTER TABLE bigtable DROP FOREIGN KEY bigtable_ibfk_1,
MODIFY smalltable_id SMALLINT ;
UPDATE bigtable SET smalltable_id=CASE smalltable_id
WHEN 1 THEN 1592
WHEN 2 THEN 1593
WHEN 3 THEN 1602
...
ELSE 0
END;
ALTER TABLE bigtable ADD CONSTRAINT bigtable_ibfk_1
FOREIGN KEY(smalltable_id) REFERENCES newsmalltable(id);
COMMIT;
END//
DELIMITER ;
CALL updatebigtable();
DROP PROCEDURE updatebigtable;
Run Code Online (Sandbox Code Playgroud)
我需要确保如果由于某种原因新的外键约束失败(例如,对于具有不同类型的列,错误会出现在最后一个alter table语句中), theUPDATE和 first 也ALTER TABLE应该回滚,即它们应该保持原样最初是。
据MySQL文档,通过使用START TRANSACTION自动提交模式,对于交易,这将禁止未允许:
一旦您执行更新(修改)表的语句,MySQL 就会将更新存储在磁盘上以使其永久化。
我只发现这个问题与我的关系最小:
如果我提到的那个错误发生在事务内部,则前面的语句已经执行并且更新“永久在磁盘上完成”......
我也尝试SET autocommit=0;在创建程序之前放置,但行为仍然相同......我错过了什么吗?或者这是 MySQL 事务回滚的预期行为?
如果有什么不同,我使用的是 MySQL v.5.6.17。
ALTER TABLE语句总是会导致隐式提交(来自 MySQL 文档的第 13.3.3 节,感谢wchiquito),这意味着即使它们在START TRANSACTION;...COMMIT;块内,也会有与该块内完成的更改数量一样多的提交。
锁定表也不是一种选择,因为(来自 问题ALTER TABLE):
如果您
ALTER TABLE在事务表上使用或者如果您使用的是 Windows,ALTER TABLE如果您LOCK TABLE对它进行了操作,则解锁该表。这样做是因为 InnoDB 和这些操作系统不能删除正在使用的表。
在执行 alter 和 update 语句时避免不必要的读/写的唯一选择是模拟以下所有步骤ALTER TABLE:
- 使用请求的结构更改创建一个名为 A-xxx 的新表。
- 将原始表中的所有行复制到 A-xxx。
- 将原始表重命名为 B-xxx。
- 将 A-xxx 重命名为您的原始表名。
- 删除 B-xxx。
这样可以在新表中进行更新(在第 2 步之后),唯一bigtable不可用的时间是在执行第 3 步和第 4 步(重命名)时。