自治事务可以使用在以下的位置:
存储过程和函数;
本地过程和函数;
包;
对象方法;
匿名块的最顶层。
其中过程、函数和包中使用自治事务很常见,大部分自治事务的情况都属于这种情况。由于对象相对使用的比较少,所以对象方法中的自治事务也是比较少见的,不过由于对象中的方法和包中的存储过程、函数十分相似,所以这种情况也是情理之中的。
剩下的两种情况,是以前所不了解的。从来没有想过对于本地过程和函数也是可以定义为自治事务的,不过本地过程定义为自治事务是十分方便的功能,使得过程中需要用到自治事务的功能时,不必再额外定义一个自治事务的存储过程,只需要在当前的过程中定义一个自治的本地过程就可以了。
一个简单的例子如下:
SQL> CREATE TABLE T_AUTO_TRANS (ID NUMBER, NAME VARCHAR2(30));
表已创建。
SQL> CREATE TABLE T_LOG (ID NUMBER, NAME VARCHAR2(30));
表已创建。
下面建立一个LOCAL PROCEDURE的自治事务的例子:
SQL> CREATE OR REPLACE PROCEDURE P_TEST ASITPUB个人空间!eb8uTvk^ k"Cc
2
*b-m {|IQq h#e yDi0 3 PROCEDURE P ASITPUB个人空间{@)M;Un$r Joh
4 PRAGMA AUTONOMOUS_TRANSACTION;ITPUB个人空间S gNO&j&j
5 BEGIN
ooaqrkS@C#e[0 6 INSERT INTO T_LOG VALUES (1, 'AUTONOMOUS_TRANSACTION');ITPUB个人空间-g!`6M7g%i,f&O3\!?dt0g
7 COMMIT;
j-?G-W T2D n3ti2rt h0 8 END;
q(uv+L l-hfS'oo0 9 ITPUB个人空间.YSg[br$r
10 BEGINITPUB个人空间W,^/tY1aLbS
11 INSERT INTO T_AUTO_TRANS VALUES (1, 'TEST');ITPUB个人空间A7],S\9_ yWZ%v
12 P;ITPUB个人空间,rR7D!HO
13 END;
O/A s9O\(S/v+T0 14 /
过程已创建。
SQL> EXEC P_TEST
PL/SQL过程已成功完成。
SQL> SELECT * FROM T_AUTO_TRANS;
ID NAME
uJT6eA8c0---------- ------------------------------
cNh{^0 1 TEST
SQL> SELECT * FROM T_LOG;
ID NAMEITPUB个人空间^gSA/Q(|
---------- ------------------------------ITPUB个人空间a9z~L+n-Q
1 AUTONOMOUS_TRANSACTION
SQL> ROLLBACK;
回退已完成。
SQL> SELECT * FROM T_AUTO_TRANS;
未选定行
SQL> SELECT * FROM T_LOG;
ID NAME
` `v5M P;N*rC0---------- ------------------------------ITPUB个人空间zW,cN;GX
1 AUTONOMOUS_TRANSACTION
由于自治事务可以使用在本地过程中,使得一个过程使用自治事务可以不再需要依赖其他的存储过程。
匿名块最顶层也是可以使用自治事务的:
SQL> INSERT INTO T_AUTO_TRANS VALUES (1, 'TEST');
已创建1行。
SQL> DECLAREITPUB个人空间dWjC+c6L
2 PRAGMA AUTONOMOUS_TRANSACTION;
nJ8]6rg*E/[0 3 BEGINITPUB个人空间?i|?&k
4 INSERT INTO T_LOG VALUES (1, 'AUTONOMOUS_TRANSACTION');
GTV_O-F1L0 5 COMMIT;
#i(Z3l9`%z8M.vlCo0 6 END;ITPUB个人空间a1P5Q |w's$z
7 /
PL/SQL过程已成功完成。
SQL> SELECT * FROM T_AUTO_TRANS;
ID NAME
uG7}"QCyv'^\4ZG3y0---------- ------------------------------ITPUB个人空间k;\1H?:Z
1 TEST
SQL> SELECT * FROM T_LOG;
ID NAME
_?:X7]I F0---------- ------------------------------ITPUB个人空间7h4qOO:BF8k;M_ g
1 AUTONOMOUS_TRANSACTIONITPUB个人空间WHg9J? K
1 AUTONOMOUS_TRANSACTION
SQL> ROLLBACK;
回退已完成。
SQL> SELECT * FROM T_AUTO_TRANS;
未选定行
SQL> SELECT * FROM T_LOG;
ID NAMEITPUB个人空间B3dA6j5i*@
---------- ------------------------------ITPUB个人空间6~r3|dLM ? Ao
1 AUTONOMOUS_TRANSACTION
Q?9s:X)g Y0 1 AUTONOMOUS_TRANSACTION
这种情况的意义没有本地过程的大,不过对于编写包含大量的SQL和PL/SQL的sql文件还是有不少帮助的。
自治事务实现的功能是自治事务的提交或回滚不影响当前的事务。同时自治事务也是看不到当前会话所做的未提交的修改的。
SQL> TRUNCATE TABLE T_AUTO_TRANS;
表被截断。
SQL> CREATE OR REPLACE PROCEDURE P_TEST ASITPUB个人空间/? n1}I)T:i8t%v
2 BEGIN
:No i5b#K!w11269677 3 INSERT INTO T_AUTO_TRANS VALUES (2, 'TEST');
,F]$P2cbt3`D11269677 4 FOR I IN (SELECT COUNT(*) CNT FROM T_AUTO_TRANS) LOOP
3UQy ]w11269677 5 DBMS_OUTPUT.PUT_LINE('P_TEST:' || I.CNT);
b#D.D~{11269677 6 END LOOP;
HK uj0f%wu2]3V11269677 7 END;
!Y&X&ql6_11269677 8 /
过程已创建。
SQL> CREATE OR REPLACE PROCEDURE P_TEST_AUTO ASITPUB个人空间 Ja5v(xt~5lJV
2 PRAGMA AUTONOMOUS_TRANSACTION;
8d4]O\H11269677 3 BEGIN
+^6I)`sC-r,D&j5Xn+L11269677 4 INSERT INTO T_AUTO_TRANS VALUES (2, 'TEST');
.c'M(?ybiZL11269677 5 FOR I IN (SELECT COUNT(*) CNT FROM T_AUTO_TRANS) LOOP
hMp+kv(u11269677 6 DBMS_OUTPUT.PUT_LINE('P_TEST_AUTO:' || I.CNT);ITPUB个人空间Z3B7X:M&Of8]
7 END LOOP;
f&dMF \b md11269677 8 COMMIT;
Lt`{q@ lIo11269677 9 END;ITPUB个人空间(t}JYoO$U'I+d
10 /
过程已创建。
SQL> INSERT INTO T_AUTO_TRANS VALUES (1, 'TEST');
已创建1行。
SQL> SET SERVEROUT ONITPUB个人空间-XOD5Ip H
SQL> EXEC P_TESTITPUB个人空间0OT*voHy HYA:R)T
P_TEST:2
PL/SQL过程已成功完成。
SQL> EXEC P_TEST_AUTOITPUB个人空间&h3lg'k z)aHCjm%B
P_TEST_AUTO:1
PL/SQL过程已成功完成。
可以看到,对于自治事务是看不到当前会话所作的未提交的修改的。
SQL> EXEC P_TESTITPUB个人空间~pNRR5w*?)x6x
P_TEST:4
PL/SQL过程已成功完成。
而对于当前会话,由于自治事务的操作已经提交,因此之后的查询是可以看到自治事务所进行的修改的。
自治事务看不到当前会话的修改,那么自治事务调用的过程是否能看到自治事务的修改呢:
SQL> TRUNCATE TABLE T_AUTO_TRANS;
表被截断。
SQL> CREATE OR REPLACE PROCEDURE P_AUTO_TRANS ASITPUB个人空间w)~%WJGIjS
2 PRAGMA AUTONOMOUS_TRANSACTION;ITPUB个人空间4h_uk$Q1c
3 BEGIN
^'`qLXbp+K11269677 4 INSERT INTO T_AUTO_TRANS VALUES (1, 'TEST');
hza+a&K11269677 5 INSERT INTO T_AUTO_TRANS VALUES (2, 'TEST');
D{3X5t1q0u11269677 6 FOR I IN (SELECT COUNT(*) CNT FROM T_AUTO_TRANS) LOOP
X:Xf0f/T8h11269677 7 DBMS_OUTPUT.PUT_LINE('P_AUTO_TRANS:' || I.CNT);
w{UV5z-q/N U6dbt lb11269677 8 END LOOP;ITPUB个人空间~]1O8m z"a(YO
9 P_TEST;
I(i/qXowu;ivo11269677 10 P_TEST_AUTO;ITPUB个人空间9O%R~#j1G
11 COMMIT;ITPUB个人空间V)?6lfZ+Px
12 END;ITPUB个人空间W P})l9Yc
13 /
过程已创建。
SQL> INSERT INTO T_AUTO_TRANS VALUES (1, 'TEST');
已创建1行。
SQL> EXEC P_AUTO_TRANS
(Nz-G'EQ4kAvw2v11269677P_AUTO_TRANS:2ITPUB个人空间@4|Pa6|0uu]H1U
P_TEST:3ITPUB个人空间!j&E8jv|
P_TEST_AUTO:1
PL/SQL过程已成功完成。
建立一个自治事务,分别调用一个普通过程和一个声明了自治事务的过程,结果可以看到,自治事务调用普通过程,可以看到自治事务所进行的修改,而对于自治事务调用的自治事务过程,是看不到自治事务所进行的修改的。
从这一点看,自治事务更像是在单独的会话中执行,它的事务状态不会影响当前的事务,它也不会看到当前事务没有提交的修改。
来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/11269677/viewspace-613433/ ,如需转载,请注明出处,否则将追究法律责任。