|
這是一個(gè)非常實(shí)用的功能,特別用在記錄錯(cuò)誤日志同時(shí)要回滾主事務(wù)的時(shí)候,我們?cè)趯?shí)際開(kāi)發(fā)中就是這么用的,感覺(jué)還是很方便的。轉(zhuǎn)載一篇詳細(xì)的介紹,感謝原作者。
在基于低版本的ORACLE做一些項(xiàng)目的過(guò)程中,有時(shí)會(huì)遇到一些頭疼的問(wèn)題.,比如想在執(zhí)行當(dāng)前一個(gè)由多個(gè)DML組成的transaction(事務(wù))時(shí),為每一步DML記錄一些信息到跟蹤表中,由于事務(wù)的原子性,這些跟蹤信息的提交將決定于主事務(wù)的commit或rollback. 這樣一來(lái)寫(xiě)程序的難度就增大了, 程序員不得不把這些跟蹤信息記錄到類(lèi)似數(shù)組的結(jié)構(gòu)中,然后在主事務(wù)結(jié)束后把它們存入跟蹤表.哎,真是麻煩!
有沒(méi)有一個(gè)簡(jiǎn)單的方法解決類(lèi)似問(wèn)題呢?
ORACLE8i的AUTONOMOUS TRANSACTION(自治事務(wù),以下AT)是一個(gè)很好的回答。
AT 是由主事務(wù)(以下MT)調(diào)用但是獨(dú)立于它的事務(wù)。在AT被調(diào)用執(zhí)行時(shí),MT被掛起,在AT內(nèi)部,一系列的DML可以被執(zhí)行并且commit或rollback.
注意由于AT的獨(dú)立性,它的commit和rollback并不影響MT的執(zhí)行效果。在AT執(zhí)行結(jié)束后,主事務(wù)獲得控制權(quán),又可以繼續(xù)執(zhí)行了。
如何實(shí)現(xiàn)AT的定義呢?我們來(lái)看一下它的語(yǔ)法。其實(shí)非常簡(jiǎn)單。
只需下列PL/SQL的聲明部分加上PRAGMAAUTONOMOUS_TRANSACTION就可以了。
可以加自治事務(wù)的有:
1. 頂級(jí)的匿名PL/SQL塊
2. Functions 或 Procedure(獨(dú)立聲明或聲明在package中都可)
3. SQL Object Type的方法
4. 觸發(fā)器。
比如:
在一個(gè)獨(dú)立的procedure中聲明AT
CREATE OR REPLACE PROCEDURE
Log_error(error_msg IN VARCHAR2(100))
IS
PRAGMA AUTONOMOUS_TRANSACTION;
BEGIN
Insert into Error_log values ( sysdate,error_msg);
COMMIT;
END;
下面我們來(lái)看一個(gè)例子,(win2000 advanced server + oracle8.1.6 , connect as scott)
建立一個(gè)表:
create table msg (msg varchar2(120));
首先,用普通的事務(wù)寫(xiě)個(gè)匿名PL/SQL塊:
declare
cnt number := -1; --} Global variables
procedure local is
begin
select count(*) into cnt from msg;
dbms_output.put_line('local: # of rows is '||cnt);
insert into msg values ('New Record');
commit;
end;
begin
delete from msg ;
commit;
insert into msg values ('Row 1');
local;
select count(*) into cnt from msg;
dbms_output.put_line('main: # of rows is '||cnt);
rollback;
local;
insert into msg values ('Row 2');
commit;
local;
select count(*) into cnt from msg;
dbms_output.put_line('main: # of rows is '||cnt);
end;
運(yùn)行結(jié)果(注意打開(kāi)serveroutput)
local: # of rows is 1 -> 子程序local中可以’看到’主匿名塊中的uncommitted記錄
main: # of rows is 2 -> 主匿名塊可以’看到’2條記錄(它們都是被local commit掉的)
local: # of rows is 2 -> 子程序local首先’看到’2條記錄,然后又commit了第三條記錄
local: # of rows is 4 -> 子程序local又’看到’了新增加的記錄(它們都是被local commit掉的),然后又commit了第五條記錄
main: # of rows is 5 -> 主匿名塊最后’看到’了所有的記錄.
從這個(gè)例子中,我們看到COMMIT和ROLLBACK的位置無(wú)論是在主匿名塊中或者在子程序中,都會(huì)影響到整個(gè)當(dāng)前事務(wù).
現(xiàn)在用AT改寫(xiě)一下匿名塊中的procedure local:
...
procedure local is
pragma AUTONOMOUS_TRANSACTION;
begin
...
重新運(yùn)行(注意打開(kāi)serveroutput)
local: # of rows is 0 -> 子程序local中無(wú)法可以’看到’主匿名塊中的uncommitted記錄 (因?yàn)樗仟?dú)立的)
main: # of rows is 2 -> 主匿名塊可以’看到’2條記錄,但只有一條是被commited.
local: # of rows is 1 -> 子程序local中可以’看到’它前一次commit的記錄,但是主匿名塊中的記錄已經(jīng)被提前rollback了
local: # of rows is 3 -> 子程序local 中可以’看到’3條記錄包括主匿名塊commit的記錄
main: # of rows is 4 ->主匿名塊最后’看到’了所有的記錄.
很明顯,AT是獨(dú)立的,在它執(zhí)行時(shí),MT被暫停了. AT的COMMIT,ROLLBACK并不影響MT的執(zhí)行.
運(yùn)用AT時(shí),有一些注意事項(xiàng),簡(jiǎn)單列舉如下:
1. 在匿名PL/SQL塊中,只有頂級(jí)的匿名PL/SQL塊可以被設(shè)為AT
2. 如果AT試圖訪問(wèn)被MT控制的資源,可能有deadlock發(fā)生.
3. Package 不能被聲明為AT,只有package所擁有的function和procedure 才能聲明為AT
4. AT程序必須以commit 或rollback結(jié)尾,否則會(huì)產(chǎn)生Oracle錯(cuò)誤ORA-06519: active autonomous transaction detected and rolled back
在程序開(kāi)發(fā)時(shí),如果充分運(yùn)用AUTONOMOUS TRANSACTION的特性,一定能取得事倍功半的效果.
本文來(lái)自CSDN博客,轉(zhuǎn)載請(qǐng)標(biāo)明出處:http://blog.csdn.net/fenglibing/archive/2009/04/10/4059924.aspx
|
|
|
來(lái)自: 月影斜 > 《學(xué)習(xí)筆記》