18

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

我想知道这是否总是如此并且根据定义,或者是否有隐藏在某处的设置会回滚事务而不是提交。

谢谢。

编辑以澄清...

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

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

4

8 回答 8

19

不,它会一直提交。

如果要回滚,则必须在 DDL 之前进行。

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

于 2009-04-08T18:25:23.170 回答
17

从技术上讲, DDL在执行之前和之后执行提交。

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

于 2009-04-08T20:32:50.383 回答
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

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

于 2009-04-08T22:34:51.493 回答
4

截断表更改表创建表总是会导致提交。

为什么要在截断表时回滚?

于 2009-04-08T15:54:53.873 回答
3

是一篇 AskTom 文章,可能会有所帮助。来自文章:

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

你能澄清一下吗?

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

那将与不这样做一样“令人困惑”。无论如何,你有atrans,所以如果你愿意,你可以。"

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

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

于 2009-04-08T18:22:11.850 回答
1

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

如果您希望它在发生故障时回滚(在服务器端),那么您可以设置某些标志来指示故障并采取适当的措施。

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

但是由于某种原因插入失败(设置标志=真)。那么在这种情况下,您不能回滚,因为创建语句是 ddl 语句,因此您可以通过删除表(表 1)来撤消数据库中的更改,具体取决于flag 的值,通过 Drop 语句。

于 2012-03-21T14:20:28.287 回答
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 时会发生争用。就像任何两个相互阻塞的事务一样。如果它们是独立的对象,我想我不明白为什么执行顺序很重要。

于 2017-03-28T20:16:44.347 回答
0

“总是/从不”太强了。例如CREATE PRIVATE TEMPORARY TABLE,来自 Oracle 18c 的 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<>小提琴演示

于 2018-03-13T15:53:11.863 回答