我可以在ALTER TABLE中使用交易吗?

时间:2014-04-02 08:56:22

标签: mysql sql transactions phpmyadmin rollback

我是SQL事务的初学者(实际上是新手),所以我可能会遗漏一些明显的东西。

我有这个SQL代码,我正试图通过 phpMyAdmin 运行:

START TRANSACTION;

INSERT INTO `users` VALUES(NULL, 'User A', 'user.a@example.com', '4', 'User A');
INSERT INTO `users` VALUES(NULL, 'User B', 'user.b@example.com', '3', 'User B');

ALTER TABLE `users` CHANGE `level` `level` TINYINT(3) UNSIGNED NOT NULL;
ALTER TABLE `users` CHANGE `number` `number` INT(10) UNSIGNED NOT NULL;
ALTER TABLE `users` ADD COLUMN `number` INT(10) UNSIGNED NOT NULL AFTER `id`;

COMMIT;

如您所见,第二个ALTER导致#1054 - Unknown column 'number' in 'users'错误。

但是,当它发生在 phpMyAdmin 中时,我可以看到,前两个INSERT(或整个事务)没有回滚。 users表确实包含两个新记录。

我错过了什么? phpMyAdmin不支持交易?或者我不明白,交易实际上是如何工作的,这是很正常的,这两个INSERT在出错时不会回滚?

1 个答案:

答案 0 :(得分:9)

执行之前的MySQL DDL 中的一些语句(最值得注意的是cause an implicit commit)和cannot be rolled back - 因此这可以防止先前的DML更改被滚动回来了。

  

本节中列出的语句(以及它们的任何同义词)隐式结束当前会话中活动的任何事务,就像在执行语句之前已完成COMMIT一样。从MySQL 5.5.3开始,大多数这些语句在执行后也会导致隐式提交;有关其他详细信息,请参阅本节末尾。

由于ALTER TABLE是受影响的语句之一,因此SQL批处理有效地被视为:

START TRANSACTION;
INSERT INTO `users` VALUES(NULL, 'User A', 'user.a@example.com', '4', 'User A');

COMMIT; -- prevents ROLLBACK of insert(s), even if DDL fails
ALTER TABLE `users` CHANGE `level` `level` TINYINT(3) UNSIGNED NOT NULL;

建议的解决方案是keep DDL and DML separateddocumentation说:

  

您应该将[DML]事务设计为不包含此类[DDL]语句。如果您在无法回滚的事务的早期发出语句,然后另一个语句失败,则在这种情况下,通过发出ROLLBACK语句无法回滚事务的完整效果。