Answers:
http://wiki.postgresql.org/wiki/Transactional_DDL_in_PostgreSQL:_A_Competitive_Analysis从PostgreSQL的角度概述了此问题。
根据此文档,DDL是否具有事务性?
SQLite也似乎也具有事务性DDL。我能够ROLLBACK
一个CREATE TABLE
在SQLite的声明。它的CREATE TABLE
文档中没有提到任何特殊的交易“陷阱”。
PostgreSQL对大多数数据库对象(某些表,索引等,但没有数据库,用户)具有事务性DDL。但是,实际上,任何DDL都会ACCESS EXCLUSIVE
锁定目标对象,从而使其完全无法访问,直到DDL事务完成。此外,并非所有情况都得到了很好的处理-例如,如果您尝试foo
在另一个事务删除它并创建替换表的同时从表中进行选择foo
,那么被阻塞的事务将最终收到错误,而不是查找新foo
表。(编辑:此问题已在PostgreSQL 9.3或更高版本中修复)
CREATE INDEX ... CONCURRENTLY
例外,它使用三个事务在允许并发更新的同时向表添加索引,因此它本身不能在事务中执行。
另外,数据库维护命令VACUUM
不能在事务中使用。
foo
在另一个事务正在删除并重新创建它的情况下尝试从表中进行选择,那么我对旧版本或错误是可以的。我对新版本不满意,因为它尚未提交,所以我一定看不到。我可以接受一个错误,因为在并发事务访问中,无论如何都必须准备重新启动事务。如果错误发生的次数多于必要的次数,则可能会降低性能,但这仍然是正确的。
看来其他答案已经过时了。
截至2019年:
START TRANSACTION ... COMMIT;
。因此,如果同一事务中的后一个DDL语句失败,则仍然无法回滚事务中的DDL语句 。 mysql.com/doc/refman/8.0/en/...)
看起来MySQL无法完成,这很愚蠢,但确实如此...(根据公认的答案)
“ InnoDB中的CREATE TABLE语句作为单个事务处理。这意味着来自用户的ROLLBACK不会撤消用户在该事务期间所做的CREATE TABLE语句。”
https://dev.mysql.com/doc/refman/5.7/zh-CN/implicit-commit.html
尝试了几种不同的方法,它根本不会回滚。
解决方法是简单地设置一个失败标志,如果其中一个查询失败,则执行“ drop table tblname”。