我是 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/