Joril Asked: 2011-01-26 00:56:23 +0800 CST2011-01-26 00:56:23 +0800 CST 2011-01-26 00:56:23 +0800 CST 为什么某些 DBMS 不允许某些 DDL 语句回滚? 772 最近我发现 MySQL不支持回滚 DDL,比如“alter table”……习惯了 PostgreSQL,这让我觉得很奇怪,但是我的一个朋友告诉我,即使是 Oracle 也不允许它..是否有不支持它的技术原因?这对他们来说仅仅是一个“无趣”的功能吗? 编辑:刚刚发现这个比较。看起来有很多 DBMS确实支持事务性 DDL。 ddl feature-comparison 4 个回答 Voted Best Answer Peter Eisentraut 2011-01-26T06:18:57+08:002011-01-26T06:18:57+08:00 这在 PostgreSQL 中起作用的原因是系统目录是常规表。因此,例如,创建一个新函数只需要在表中插入一行pg_proc,更改列的默认值只需要对 中的某些行进行更新pg_attrdef,等等。由于表格无论如何都是事务性的,因此您几乎必须竭尽全力不让它以这种方式工作。(这里省略了很多痛苦的实现细节。;-)) 我想,不知道源代码,其他数据库引擎使用一些自定义的内部结构来表示他们的系统目录信息。因此,他们必须付出额外的努力,可能会付出很多额外的努力,才能使事务性 DDL 工作,而这显然不是他们的优先事项。 另一方面,这就是 PostgreSQL 的主要版本升级如此痛苦的原因。其他产品可能会在设计其内部元数据结构时考虑到更改和更新,因此升级到新的主要版本没有问题。在 PostgreSQL 中,无法将系统目录表更改为突然看起来像系统目录表的更新版本,至少在保持系统在线时不会,因为这需要访问系统目录。呃。 KillerDBA 2011-01-26T14:11:15+08:002011-01-26T14:11:15+08:00 大多数没有?真可惜。 我主要使用 SQL Server,它确实如此。我知道甲骨文没有,但我认为甲骨文可能是一个异常。 在 SQL Server 中,我很确定您可以在单个事务中运行多个 DDL 语句,尽管我也认为有一些限制(我都忘记了)。如果您愿意,您可以创建、更改或删除大多数内容并将其回滚。Red-Gate SQL Compare(我喜欢的一个工具)利用了这一点。 这样做的问题是您的事务范围变得相当有趣......当您在更新事务 (DDL) 中涉及系统目录时,您会冒着获取一些非常重要的锁的风险,并且您可能会阻止对系统目录的访问。如果他们的查询在目录中找不到他们的表,用户将无能为力! 不过,总的来说,能够在多语句事务中包含 DDL 是很方便的。 更有用的是,SQL Server DDL 命令TRUNCATE 也可以是多语句事务的一个元素。您可以截断目标表(非常快),构建它,然后如果您喜欢结果,请执行提交。如果出现问题,您回滚并瞧!就像您从未打扰过桌子一样。日志空间也被最小化。我经常利用这一点。 Marian 2011-01-26T03:56:12+08:002011-01-26T03:56:12+08:00 在 SQL Server 中,我们可以回滚 DDL 语句,它不是在语句末尾使用自动提交。在其他 DBMS 中我不知道,但我记得在 Oracle 中不能这样做。我相信它特定于每个 DBMS,不确定 SQL 标准对此有何看法,但我确信没有生产者 100% 实施该标准。 SO上有一个类似的问题:Is it possible to run multiple DDL statements inside a transaction (within SQL Server)? Gary 2011-01-26T13:03:04+08:002011-01-26T13:03:04+08:00 Oracle 具有共享查询解析,因此一个会话完成的 SELECT * FROM table_a (通常)与另一个会话的相同。如果一个会话认为表格中有十列,而另一个认为有十一列,那将会中断。
这在 PostgreSQL 中起作用的原因是系统目录是常规表。因此,例如,创建一个新函数只需要在表中插入一行
pg_proc
,更改列的默认值只需要对 中的某些行进行更新pg_attrdef
,等等。由于表格无论如何都是事务性的,因此您几乎必须竭尽全力不让它以这种方式工作。(这里省略了很多痛苦的实现细节。;-))我想,不知道源代码,其他数据库引擎使用一些自定义的内部结构来表示他们的系统目录信息。因此,他们必须付出额外的努力,可能会付出很多额外的努力,才能使事务性 DDL 工作,而这显然不是他们的优先事项。
另一方面,这就是 PostgreSQL 的主要版本升级如此痛苦的原因。其他产品可能会在设计其内部元数据结构时考虑到更改和更新,因此升级到新的主要版本没有问题。在 PostgreSQL 中,无法将系统目录表更改为突然看起来像系统目录表的更新版本,至少在保持系统在线时不会,因为这需要访问系统目录。呃。
大多数没有?真可惜。
我主要使用 SQL Server,它确实如此。我知道甲骨文没有,但我认为甲骨文可能是一个异常。
在 SQL Server 中,我很确定您可以在单个事务中运行多个 DDL 语句,尽管我也认为有一些限制(我都忘记了)。如果您愿意,您可以创建、更改或删除大多数内容并将其回滚。Red-Gate SQL Compare(我喜欢的一个工具)利用了这一点。
这样做的问题是您的事务范围变得相当有趣......当您在更新事务 (DDL) 中涉及系统目录时,您会冒着获取一些非常重要的锁的风险,并且您可能会阻止对系统目录的访问。如果他们的查询在目录中找不到他们的表,用户将无能为力!
不过,总的来说,能够在多语句事务中包含 DDL 是很方便的。
更有用的是,SQL Server DDL 命令
TRUNCATE
也可以是多语句事务的一个元素。您可以截断目标表(非常快),构建它,然后如果您喜欢结果,请执行提交。如果出现问题,您回滚并瞧!就像您从未打扰过桌子一样。日志空间也被最小化。我经常利用这一点。在 SQL Server 中,我们可以回滚 DDL 语句,它不是在语句末尾使用自动提交。在其他 DBMS 中我不知道,但我记得在 Oracle 中不能这样做。我相信它特定于每个 DBMS,不确定 SQL 标准对此有何看法,但我确信没有生产者 100% 实施该标准。
SO上有一个类似的问题:Is it possible to run multiple DDL statements inside a transaction (within SQL Server)?
Oracle 具有共享查询解析,因此一个会话完成的 SELECT * FROM table_a (通常)与另一个会话的相同。如果一个会话认为表格中有十列,而另一个认为有十一列,那将会中断。