赞
踩
嵌套事务(Nested Transaction): 指在主事务(MT)中嵌套的一个或多个子事务,并且子事务与主事务相互影响。
自治事务(Autonomous Transaction):由主事务调用但又独立于主事务,子事务对commit和rollback进行自治管理,不影响主事务执行效果。常用于写入LOG或TRACE信息便于查找错误。
1.预备Create Table
- create table TEST_POLICY
- (
- POLICY_CODE VARCHAR2(20),
- POLICY_TYPE CHAR(1)
- );
2. 创建一个嵌套事务procedure
- Procedure P_Insert_Policy(I_Policy_code varchar2(20),I_Policy_type char(1)) as
- cnt number :=0;
- begin
- select count(1) into cnt from Test_Policy;
- Dbms_Output.put_line('records of the test_policy is '|| cnt);
-
- Insert into Test_Policy values(I_Policy_code, I_Policy_type);
- commit;--commit in nested transaction
- end P_Insert_Policy;
-
- --call procedure used in nested transaction
- PROCEDURE TEST_PL_SQL_ENTRY(I_POL_ID IN VARCHAR2,O_SUCC_FLG OUT VARCHAR2) AS
- strSql varchar2(500);
- cnt number := 0;
- BEGIN
- delete from test_policy;
- commit;
- insert into test_policy values('2010042101', '1');
- select count(1) into cnt from Test_Policy;
- Dbms_Output.put_line('records of the test_policy is '|| cnt);
- --call nested transaction
- P_Insert_Policy('2010042102', '2');
- rollback;--rollback data for all transactions
- commit;--master transaction commit
- select count(1) into cnt from Test_Policy;
- Dbms_Output.put_line('records of the test_policy is '|| cnt);
- rollback;
- select count(1) into cnt from Test_Policy;
- Dbms_Output.put_line('records of the test_policy is '|| cnt);
- END TEST_PL_SQL_ENTRY;
运行输出结果如下:
将上面的nested transaction的procedure修改一下,不进行commit:
- Procedure P_Insert_Policy(I_Policy_code T_contract_master.Policy_Code%type,
- I_Policy_type t_contract_master.policy_type%type) as
- cnt number :=0;
- begin
- select count(1) into cnt from Test_Policy;
- Dbms_Output.put_line('records of the test_policy is '|| cnt);
- Insert into Test_Policy values(I_Policy_code, I_Policy_type);
- --commit;
- end P_Insert_Policy;
-
- PROCEDURE TEST_PL_SQL_ENTRY(I_POL_ID IN VARCHAR2, O_SUCC_FLG OUT VARCHAR2) AS
- strSql varchar2(500);
- cnt number := 0;
- BEGIN
- delete from test_policy;
- commit;
- insert into test_policy values('2010042101', '1');
- select count(1) into cnt from Test_Policy;
- Dbms_Output.put_line('records of the test_policy is '|| cnt);
-
- P_Insert_Policy('2010042102', '2');
- rollback;
- commit;
- select count(1) into cnt from Test_Policy;
- Dbms_Output.put_line('records of the test_policy is '|| cnt);
- rollback;
-
- select count(1) into cnt from Test_Policy;
- Dbms_Output.put_line('records of the test_policy is '|| cnt);
-
- END TEST_PL_SQL_ENTRY;
运行输出结果如下:
以下类型的 PL/SQL blocks 可以被定义为自治事务:
定义方法非常简单,在 DECLARE 后加上 PRAGMA AUTONOMOUS_TRANSACTION 即可。
来看一个简单的例子,注意以下在一个会话内执行
- CREATE TABLE at_test (
- id NUMBER NOT NULL,
- description VARCHAR2(50) NOT NULL
- );
-
- INSERT INTO at_test (id, description) VALUES (1, 'Description for 1');
- INSERT INTO at_test (id, description) VALUES (2, 'Description for 2');
- -- 不要提交
-
- SELECT * FROM at_test;
-
- ID DESCRIPTION
- ---------- --------------------------------------------------
- 1 Description for 1
- 2 Description for 2
-
- 2 rows selected.
-
- -- 自治事务plsql block
- DECLARE
- PRAGMA AUTONOMOUS_TRANSACTION;
- cnt number := 0;
- BEGIN
- select count(*) into cnt from at_test;
- Dbms_Output.put_line('cnt: '|| cnt); -- 输出0,因为自治事务不受主事务影响
- FOR i IN 3 .. 10 LOOP
- INSERT INTO at_test (id, description)
- VALUES (i, 'Description for ' || i);
- END LOOP;
- COMMIT;
- select count(*) into cnt from at_test;
- Dbms_Output.put_line('cnt: '|| cnt); -- 输出8,插入8行
- END;
- /
-
- -- 回到主事务查询,一共十行(提交的自治事务影响主事务)
- SELECT * FROM at_test;
-
- ID DESCRIPTION
- ---------- --------------------------------------------------
- 1 Description for 1
- 2 Description for 2
- 3 Description for 3
- 4 Description for 4
- 5 Description for 5
- 6 Description for 6
- 7 Description for 7
- 8 Description for 8
- 9 Description for 9
- 10 Description for 10
-
- 10 rows selected.
-
- -- 回滚,再查询,发现主事务插入的2行没了,自治事务插入的还在
- ROLLBACK;
- SELECT * FROM at_test;
-
- ID DESCRIPTION
- ---------- --------------------------------------------------
- 3 Description for 3
- 4 Description for 4
- 5 Description for 5
- 6 Description for 6
- 7 Description for 7
- 8 Description for 8
- 9 Description for 9
- 10 Description for 10
-
- 8 rows selected.
再看一个与前面嵌套事务对应的例子:
- create Procedure p_insert_policy_new(i_policy_code Varchar2(20), i_policy_type char(1)) as
- Pragma Autonomous_Transaction; --定义自治事务
- cnt number := 0;
- begin
- select count(1) into cnt from test_policy;
- Dbms_Output.put_line('records of the test policy table is: '||cnt);
- Insert into Test_Policy values(I_Policy_code, I_Policy_type);
- commit;
- select count(1) into cnt from test_policy;
- Dbms_Output.put_line('records of the test policy table is: '||cnt);
- end p_insert_policy_new;
- /
-
- --call auto trans procedure
- create PROCEDURE TEST_PL_SQL_ENTRY(I_POL_ID IN VARCHAR2, O_SUCC_FLG OUT VARCHAR2) AS
- strSql varchar2(500);
- cnt number := 0;
- v_policyCode t_contract_master.policy_code%type;
- BEGIN
- delete from test_policy;
- commit;
- insert into test_policy values('2010042101', '1');
- select count(1) into cnt from Test_Policy;
- Dbms_Output.put_line('records of the test_policy is '|| cnt);
-
- p_insert_policy_new('2010042102', '2');
- select count(1) into cnt from Test_Policy;
- Dbms_Output.put_line('records of the test_policy is '|| cnt);
- rollback;
- select policy_code into v_policyCode from test_policy;
- Dbms_Output.put_line('policy_code: '|| v_policyCode);
- select count(1) into cnt from Test_Policy;
- Dbms_Output.put_line('records of the test_policy is '|| cnt);
-
- END TEST_PL_SQL_ENTRY;
- /
运行结果如下:
下面是一个用自治事务收集报错日志信息的例子:
定义一个自治事务存储过程
- CREATE OR REPLACE PROCEDURE log_errors (p_error_message IN VARCHAR2) AS
- PRAGMA AUTONOMOUS_TRANSACTION;
- BEGIN
- INSERT INTO error_logs (id, log_timestamp, error_message)
- VALUES (error_logs_seq.NEXTVAL, SYSTIMESTAMP, p_error_message);
- COMMIT;
- END;
- /
外层代码调用存储过程,报错时记录日志
- BEGIN
- INSERT INTO at_test (id, description) VALUES (998, 'Description for 998');
- -- Force invalid insert.
- INSERT INTO at_test (id, description) VALUES (999, NULL);
-
- EXCEPTION
- WHEN OTHERS THEN
- log_errors (p_error_message => SQLERRM);
- ROLLBACK;
- END;
- /
-
- SELECT * FROM at_test WHERE id >= 998;
- no rows selected
-
- SELECT * FROM error_logs;
-
- ID LOG_TIMESTAMP ERROR_MESSAGE
- ---------- ----------------------- -----------------------------------------------
- 1 28-FEB-2006 11:10:10.107625 ORA-01400: cannot insert NULL into ("TIM_HALL"."AT_TEST"."DESCRIPTION")
参考
https://blog.csdn.net/xujinyang/article/details/7029848
https://oracle-base.com/articles/misc/autonomous-transactions
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。