mysql - 我可以将事务与 ALTER TABLE 一起使用吗?

标签 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 不会在出错时回滚?

最佳答案

MySQL DDL 中的一些语句(最著名的是 cause an implicit commit) 它们被执行之前cannot be rolled back - 因此,这可以防止先前的 DML 更改也被回滚。

The statements listed in this section (and any synonyms for them) implicitly end any transaction active in the current session, as if you had done a COMMIT before executing the statement. As of MySQL 5.5.3, most of these statements also cause an implicit commit after executing; for additional details, see the end of this section.

由于 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 separated . documentation说:

You should design your [DML] transactions not to include such [DDL] statements. If you issue a statement early in a transaction that cannot be rolled back, and then another statement later fails, the full effect of the transaction cannot be rolled back in such cases by issuing a ROLLBACK statement.

关于mysql - 我可以将事务与 ALTER TABLE 一起使用吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22806261/

相关文章:

sql - 获取 MySQL 更新语句中受影响的行数?

java - Spring MVC 4 + JSP + JDBC

php - 如何从标签列表的标签栏中准确选择标签?

mysql - 找到一个匹配项时获取所有加入的记录

sql - AWS ATHENA 将列转置为行

MySQL 数据库结构将值推送到一个字段或创建新表

PHP PDO 异常

php - 从表单中的第二个表发布变量

c# - 完全托管的数据库解决方案?

grails - 启用级联保存和事务的Grails域关联