DDL 语句总是给你一个隐式提交,还是你能得到一个隐式回滚?

问题描述 投票:0回答:8

如果您在事务的中途执行 DDL 语句,例如截断表,则事务提交。

我想知道这是否总是如此,根据定义,还是有一个隐藏的设置会 rollback 事务而不是提交。

谢谢。

编辑澄清...

我不想在截断后回滚。我只是想确认已经执行的语句 绝对总是 将在 DDL 之前提交。只是想确保没有某个系统属性可以设置为破坏我的代码。

我理解在 DDL 之前和之后提交的必要性,但从概念上讲,我认为相同的一致性要求可以通过在 DDL 之前回滚和之后提交来实现。

sql oracle transactions ddl
8个回答
22
投票
不,它总是会提交。

如果你想回滚,你必须在 DDL 之前做。

如果您想将 DDL 与现有事务隔离开来,则必须在其自己的单独事务中执行它。


18
投票
技术上

DDL在执行之前和执行之后进行提交。

是来自 Cookie 的相同链接,但这是同一问题的不同方面。重要的是要了解这不仅仅是一次提交,还有两次,它们发生在之前和之后。


6
投票
实际上,如果可以的话,它会提交。如果不能成功提交,DDL 将失败。 阻止它提交的一种方法是违反延迟约束。

create table fred (id number); alter table fred add constraint id_ck check (id >0) initially deferred; insert into fred values (-1); SQL> create table junk(val number); create table junk(val number) * ERROR at line 1: ORA-02091: transaction rolled back ORA-02290: check constraint (GC_REF.ID_CK) violated SQL> desc junk ERROR: ORA-04043: object junk does not exist

所以如果你想防止隐式提交,有一个带有延迟约束的虚拟表。在其中插入一个违规行,您可以确保在解决违规(例如删除行)之前无法提交事务。


4
投票
A

truncate tablealter tablecreate table 总是会导致提交。

做truncate table为什么要回滚?


3
投票

这里 是一篇可能有帮助的 AskTom 文章。来自文章:

“我想知道为什么 DDL 语句不在自主事务中执行(就像序列那样),所以它们不会影响任何未决的用户事务......

你能澄清一下吗?

跟进 2003 年 6 月 24 日 - 美国东部时间早上 7 点:

那会和不那样做一样“令人困惑”。不管怎样,你有反式翻译,所以如果你想,你可以。 “

所以,如果你真的需要,你可以把你的 DDL 放在一个自治事务中,然后做你想做的事。

编辑: 底线是,除非您竭尽全力“颠覆”Oracle,否则 DDL 将执行提交。就是说,如果您绝对需要在某个时间点执行提交,为什么不明确地执行它呢?


1
投票
DDL 语句总是在执行后执行自动提交。

如果你想让它在失败的情况下回滚(在服务器端),那么你可以设置某些标志来指示失败并采取适当的行动。

例如: 如果您已经创建了一个表 table1。 同时你在其他表中插入一条记录。

但是由于某些原因插入失败(设置标志=真)。那么在那种情况下 你不能回滚,因为 create 语句是一个 ddl 语句,所以你可以通过 Drop 语句根据标志的值删除表(table1)来撤消数据库中的更改。


0
投票
我同意 DCookie 和 Tom 关于自主交易的观点。我也打算说明这一点。

示例伪代码:

Do some DML Call autonomous function, that performs DDL Do some more DML rollback or commit all the DML - your choice

虽然我不认为这很有用。如果初始 DML 和 DDL 涉及同一个表/对象,它将无法工作。当您尝试执行 DDL 时,您会遇到争用。就像任何两个相互阻塞的事务一样。如果它们是独立的对象,我想我不明白为什么执行顺序很重要。


0
投票
“总是/从不”太强了。例如来自 Oracle 18c 的像

CREATE PRIVATE TEMPORARY TABLE

 这样的 DDL 不会 
COMMIT
 您的交易。

正常场景:

CREATE TABLE t(i INT); INSERT INTO t(i) VALUES(21); CREATE TABLE x(i INT); -- same for CREATE GLOBAL TEMPORARY TABLE y(i INT); ROLLBACK; SELECT * FROM t; -- Output: -- 21

但是如果你创建私有表:

CREATE TABLE t(i INT); INSERT INTO t(i) VALUES(21); CREATE PRIVATE TEMPORARY TABLE ORA$PTT_temp(i INT); -- or CREATE PRIVATE TEMPORARY TABLE ORA$PTT_tab AS SELECT 1 AS c FROM dual; ROLLBACK; SELECT * FROM t; -- Output: -- no data found

db<>小提琴演示

© www.soinside.com 2019 - 2024. All rights reserved.