现在的位置: 首页 > 综合 > 正文

【DDL】DDL的隐式commit和自治事务

2013年12月02日 ⁄ 综合 ⁄ 共 3077字 ⁄ 字号 评论关闭

DDL的隐式commit和自治事务

 

DDL的隐式commit

ddl的执行过程

Begin

  Commit;

  Ddl;

  Commit;

Exception

  When others then

       Rollback;

       Raise;

End;

很清楚,在真正执行ddl操作前后共执行了两次commit操作,这两次commit操作是自动执行的。即使ddl语句因为某种原因执行失败(ddl语句本身语法错误除外),也会执行第一次commit,但不会执行第二次commit,而是rollback。

 

假设我们执行了DML操作,没有commit,紧接着在同会话里继续执行了ddl操作。此时,之前的DML操作就会被自动commit。我们可以使用自治事务来避免这个问题。

 

自治事务

所谓自治事务(autonomous transaction)就是创建一个“事务中的事务”,它能独立于其父事务提交或回滚。利用自治事务,可以挂起当前执行的事务,开始一个新的事务,完成一些工作,然后提交或回滚,所有这些操作都不影响父事务的状态。上面的例子中,DML操作就相当于父事务,DDL操作就相当于自治事务,DDL中的两次commit操作不会对DML操作中的状态产生任何影响,也就是不会commit ddl操作。下面的例子中将利用过程和匿名块对自治事务和ddl 的auto commit进行演示。

-----------------------------------------------------------------------------------------------------------------------------------

0.演示思路

有两个表t0,t1。在会话1中:表t0上进行dml操作:Insert不commit,然后在同一个回话中truncate t2表,然后从会话2中查询t0表,预想:完成了commit操作,看到insert插入的记录,证明了ddl操作的隐式提交。接着清除t0表上的数据,执行dml操作insert,但不commit。然后在同一个会话中执行自治事务的DDL操作:truncate t2表。然后在会话2中查询t0表,预想:dml操作还没有commit,所以看不到insert插入的记录,证明了自治事务避免了ddl操作的隐式提交。

 

1.版本

BALLONTT@TEST> select * from v$version;

 

BANNER

----------------------------------------------------------------

Oracle Database 10g Enterprise Edition Release10.2.0.1.0 - Prod

PL/SQL Release 10.2.0.1.0 - Production

CORE   10.2.0.1.0      Production

TNS for Linux: Version 10.2.0.1.0 - Production

NLSRTL Version 10.2.0.1.0 – Production

 

2.创建环境

在会话1中:

BALLONTT@TEST> create table t0(name varchar2(10));

Table created.

BALLONTT@TEST> create table t1(name varchar2(10));

Table created.

 

创建truncate t1表的普通过程NonAuto:

BALLONTT@TEST> create or replace procedure NonAuto

  2  as

  3  begin

  4  DBMS_UTILITY.EXEC_DDL_STATEMENT(

  5  'truncate table t1');

  6  end;

  7  /

 

创建truncate t1表的自治事务的过程Auto:

BALLONTT@TEST> create or replace procedureAuto  

  2  as

  3   pragma autonomous_transaction;

  4  begin

  5  DBMS_UTILITY.EXEC_DDL_STATEMENT('

  6  truncate table t1');

  7  end;

  8  /

Procedure created.

注意这里使用了pragama AUTONOMOUS_TRANSACTION。这个指令告诉数据库,执行这个过程时要作为一个新的自治事务来执行,而且独立于其父事务

 

3.正常情况下的DDL操作

在会话1中:

BALLONTT@TEST> insert into t0 values('b');

1 row created.

不提交

 

在会话2中:

BALLONTT@TEST> select * from t0;

no rows selected

 

在会话1中:(执行普通的DDL操作)

BALLONTT@TEST> begin

  2  NonAuto;

  3  end;

  4  /

PL/SQL procedure successfully completed.

 

在会话2中:

BALLONTT@TEST> select * from t0;

NAME

----------

B

会话1中的dml操作已经被隐式提交

 

4.自治事务下的DDL操作

清除数据

BALLONTT@TEST> truncate table t0;

Table truncated.

BALLONTT@TEST> select * from t0;   

no rows selected

BALLONTT@TEST> insert into t0 values('c');

1 row created.

BALLONTT@TEST> select * from t0;

NAME

----------

C

 

在会话2中:

BALLONTT@TEST> select * from t0;

no rows selected

 

在会话1中:(执行自治事务的DDL)

BALLONTT@TEST> begin

  2  Auto;

  3  end;

  4  /

PL/SQL procedure successfully completed.

 

在会话2中:

BALLONTT@TEST> select * from t0;

no rows selected

会话1中的DML操作没有被DDL操作隐式commit;

补充:为什么要在DDL上进行自动commit?TOM在asktom上给出了如下回答

Tom说:
a user that gets blocked on the "do the ddl" inside the savepoint is blocked on the transaction -- 
not the "subtransaction".  Hence it would block people on the data dictionary -- a place we cannot 
afford to get jammed up.
The data dictionary is "special" -- it drives the rest of the system.  If portions of it get locked 
up for extended periods of time -- it could be deadly.

DDL操作也就是数据定义语言,对表的结构进行修改,这个修改其实就是对数据字典中表的定义进行了修改。DDL操作发生了阻塞,那么”阻塞“这个动作其实是发生在了数据字典表上,在数据字典上发生严重的阻塞可不是一个小问题,数据字典和整个数据库相关连着,在数据字典上的长期阻塞可能会造成严重的问题。因此,在每个DDL执行后自动commit,提高数据库的整天性能。

抱歉!评论已关闭.