【DDL】DDL的隱式commit和自治事務

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,提高數據庫的整天性能。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章