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 Release 10.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 procedure Auto
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,提高数据库的整天性能。
ballontt
2013/4/26
---The End---
如需转载,请标明出处和链接,大谢!
来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/27425054/viewspace-759400/,如需转载,请注明出处,否则将追究法律责任。
转载于:http://blog.itpub.net/27425054/viewspace-759400/