轉自 http://blog.csdn.net/pan_tian/article/details/7675800
這段時間遇到一個問題,程序里明明插入了一條記錄,但在后邊的一段Procedure中卻查不到剛剛插入的記錄,最后發現這個Procedure的定義中加入了PRAGMA AUTONOMOUS_TRANSACTION。
PRAGMA AUTONOMOUS_TRANSACTION中文翻譯過來叫“自治事務”(翻譯的還算好理解),對於定義成自治事務的Procedure,實際上相當於一段獨立運行的程序段,這段程序不依賴於主程序,也不干涉主程序
自治事務的特點
第一,這段程序不依賴於原有Main程序,比如Main程序中有未提交的數據,那么在自治事務中是查找不到的。
第二,在自治事務中,commit或者rollback只會提交或回滾當前自治事務中的DML,不會影響到Main程序中的DML。
Autonomous Transaction Demo 1
Without Pragma Autonomous Transaction
- CREATE TABLE t (
- test_value VARCHAR2(25));
- CREATE OR REPLACE PROCEDURE child_block IS
- BEGIN
- INSERT INTO t
- (test_value)
- VALUES
- ('Child block insert');
- COMMIT;
- END child_block;
- /
- CREATE OR REPLACE PROCEDURE parent_block IS
- BEGIN
- INSERT INTO t
- (test_value)
- VALUES
- ('Parent block insert');
- child_block;
- ROLLBACK;
- END parent_block;
- /
- -- run the parent procedure
- exec parent_block
- -- check the results
- SELECT * FROM t;
- Output:
- Parent block insert
- Child block insert
With Pragma Autonomous Transaction
- CREATE OR REPLACE PROCEDURE child_block IS
- PRAGMA AUTONOMOUS_TRANSACTION;
- BEGIN
- INSERT INTO t
- (test_value)
- VALUES
- ('Child block insert');
- COMMIT;
- END child_block;
- /
- CREATE OR REPLACE PROCEDURE parent_block IS
- BEGIN
- INSERT INTO t
- (test_value)
- VALUES
- ('Parent block insert');
- child_block;
- ROLLBACK;
- END parent_block;
- /
- -- empty the test table
- TRUNCATE TABLE t;
- -- run the parent procedure
- exec parent_block;
- -- check the results
- SELECT * FROM t;
- Output:
- Child block insert
Autonomous Transaction Demo 2
Without Pragma Autonomous Transaction
- DROP TABLE t;
- CREATE TABLE t (testcol NUMBER);
- CREATE OR REPLACE FUNCTION howmanyrows RETURN INTEGER IS
- i INTEGER;
- BEGIN
- SELECT COUNT(*)
- INTO i
- FROM t;
- RETURN i;
- END howmanyrows;
- /
- CREATE OR REPLACE PROCEDURE testproc IS
- a INTEGER;
- b INTEGER;
- c INTEGER;
- BEGIN
- SELECT COUNT(*)
- INTO a
- FROM t;
- INSERT INTO t VALUES (1);
- COMMIT;
- INSERT INTO t VALUES (2);
- INSERT INTO t VALUES (3);
- b := howmanyrows;
- INSERT INTO t VALUES (4);
- INSERT INTO t VALUES (5);
- INSERT INTO t VALUES (6);
- COMMIT;
- SELECT COUNT(*)
- INTO c
- FROM t;
- dbms_output.put_line(a);
- dbms_output.put_line(b);
- dbms_output.put_line(c);
- END testproc;
- /
- set serveroutput on
- exec testproc
- Output:
- 0
- 3
- 6
- Total execution time 2.782 sec.
With Pragma Autonomous Transaction
- CREATE OR REPLACE FUNCTION howmanyrows RETURN INTEGER IS
- i INTEGER;
- PRAGMA AUTONOMOUS_TRANSACTION;
- BEGIN
- SELECT COUNT(*)
- INTO i
- FROM t;
- RETURN i;
- END howmanyrows;
- /
- -- empty the test table
- TRUNCATE TABLE t;
- exec testproc;
- Output:
- 0
- 1
- 6
在觸發器中操作觸發此觸發器的表,用PRAGMA AUTONOMOUS_TRANSACTION選項。
15.1為何使用自治事務 無法回滾的審計
一般情況下利用觸發器禁止某些對表的更新等操作時,若記錄日志,則觸發器最后拋出異常時會造成日志回滾。利用自治事務可防止此點。
避免變異表
即在觸發器中操作觸發此觸發器的表
在觸發器中使用DDL 寫數據庫
對數據庫有寫操作(INSERT、UPDATE、DELETE、CREATE、ALTER、COMMIT)的存儲過程或函數是無法簡單的用SQL來調用的,此時可以將其設為自治事務,從而避免ORA-14552(無法在一個查詢或DML中執行DDL、COMMIT、ROLLBACK)、ORA-14551(無法在一個查詢中執行DML操作)等錯誤。需要注意的是函數必須有返回值,但僅有IN參數(不能有OUT或IN/OUT參數)。
開發更模塊化的代碼
在大型開發中,自治事務可以將代碼更加模塊化,失敗或成功時不會影響調用者的其它操作,代價是調用者失去了對此模塊的控制,並且模塊內部無法引用調用者未提交的數據。
15.2 如何工作 事務控制
DECLARE整個塊都是屬於父事務的,自治事務從離PRAGMA后的第一個BEGIN開始,只要此BEGIN塊仍在作用域,則都屬於自治事務。例如在DECLARE模塊中聲明一個寫數據庫的函數,則此函數雖然在自治事務所在存儲過程執行,但其屬於父事務;而自治事務中調用的任何函數和存儲過程、激發的任何觸發器等均為此自治事務的一部分。
自治事務可以嵌套,嵌套深度等只受INIT.ORA參數TRANSACTIONS(同時並發的事務數,缺省為SESSIONS的1.1倍)制約。
作用域
1. 包中的變量
自治事務可看到並修改父事務的變量,父事務也會察覺到這一改變,且不存在回滾問題。
2. 會話設置/參數
自治事務與父事務共享同一個會話環境,通過ALTER SESSION作的修改對整個會話均有效。但SET TRANSACTION是事務級的,僅對提起修改的事務有效。
3. 數據庫修改
父事務已提交的修改對自治事務可見,未提交的對自治事務不可見,自治事務的修改對父事務是否可見取決於隔離級別(Isolation Level)。
對於游標,取決於其打開的位置,若其在父事務中打開,則之前父事務未提交的修改對其是有效的,在自治事務中這些修改也可見;而在自治事務中打開,則父事務未提交的修改不可見。
若使用缺省的READ COMMITTED隔離級別,則自治事務的修改對父事務可見;若改用SERIALIZABLE,則不可見。
4. 鎖
父事務與自治事務是完全不同的事務,因此無法共享鎖等。
結束一個自治事務必須提交一個COMMIT、ROLLBACK或執行DDL。
保存點無法在自治事務中回滾到父事務中的一個保存點,只能在內部使用保存點。
15.3 最后說明 不支持分布式事務截至8.1.7在自治事務中不支持分布式事務
僅可用PL/SQL 全部事務回滾若自治事務出錯,則全部回滾,即便父事務有異常處理模塊。
事務級臨時表每個會話僅一個事務可訪問事務級臨時表(多個會話中的事務可並發操作)。
15.4 可能遇到的錯誤
ORA-06519 – 檢查到活動自治事務,回滾——退出自治事務時沒有提交、回滾或DDL操作
ORA-14450 – 試圖訪問正在使用的事務級臨時表
ORA-00060 – 等待資源時檢查到死鎖
在create prodedure 時可以指定PRAGMA AUTONOMOUS_TRANSACTION;
當前的存儲過程作為已有事務的子事務運行,子事務的commit,rollback操作不影響父事務的狀態
有的時候,希望在select語句中使用自己定義的函數,並且這個函數除了返回特定的值之外,還執行update,insert,delete等操作。
對數據庫有寫操作(update,insert,delete,crate,alert,commit)的函數是無法簡單的用SQL來調用的。
ORA-14551: cannot perform. a DML operation inside a query
如何實現?關鍵是pragma autonomous_transaction
如下例子:
Create or replace function func_getid return int is
2 pragma autonomous_transaction;
3 vid int;
4 begin
5 select max(id) into vid from test_id;
6 update test_id set id=id+1;
7 commit;
8 return vid;
9 end;
10 /
Function created
select func_getid from dual;
FUNC_GETID
----------
1
select func_getid from dual;
FUNC_GETID
----------
2
PRAGMA AUTONOMOUS_TRANSACTION 自治事物
DROP TABLE test_1;
CREATE TABLE test_1 (ID NUMBER PRIMARY KEY , NAME VARCHAR2(20));
CREATE OR REPLACE PROCEDURE test_proce IS
2 PRAGMA AUTONOMOUS_TRANSACTION; -------------自治事物的標示
3 BEGIN
4 INSERT INTO test_1 VALUES(2,'peter');
5 COMMIT;
6 END;
7 /
BEGIN
2 INSERT INTO test_1 VALUES(1,'joe');
3 test_proce; -----------------只COMMIT了自己沒有全局COMMIT
4 ROLLBACK; -----------------只有回滾了joe
5 END;
6 /
SELECT * FROM test_1;
ID NAME
---------- --------------------
2 peter