当前位置:   article > 正文

Oracle 嵌套事务 VS 自治事务_oracle 事务嵌套

oracle 事务嵌套

一、 概念

嵌套事务(Nested Transaction): 指在主事务(MT)中嵌套的一个或多个子事务,并且子事务与主事务相互影响。

自治事务(Autonomous Transaction):由主事务调用但又独立于主事务,子事务对commit和rollback进行自治管理,不影响主事务执行效果。常用于写入LOG或TRACE信息便于查找错误。

 

二、 嵌套事务

1.预备Create Table

  1. create table TEST_POLICY   
  2. (   
  3.     POLICY_CODE VARCHAR2(20),   
  4.     POLICY_TYPE CHAR(1)   
  5. );

2. 创建一个嵌套事务procedure

  1. Procedure P_Insert_Policy(I_Policy_code varchar2(20),I_Policy_type char(1)) as    
  2.       cnt number :=0;   
  3.       begin   
  4.           select count(1into cnt from Test_Policy;   
  5.           Dbms_Output.put_line('records of the test_policy is '|| cnt);   
  6.              
  7.           Insert into Test_Policy values(I_Policy_code, I_Policy_type);   
  8.           commit;--commit in nested transaction    
  9.       end P_Insert_Policy;
  10.     
  11. --call procedure used in nested transaction   
  12.       PROCEDURE TEST_PL_SQL_ENTRY(I_POL_ID IN VARCHAR2,O_SUCC_FLG OUT VARCHAR2) AS   
  13.       strSql varchar2(500);   
  14.       cnt number := 0;   
  15.       BEGIN   
  16.          delete from test_policy;   
  17.          commit;   
  18.          insert into test_policy values('2010042101''1');   
  19.          select count(1into cnt from Test_Policy;   
  20.          Dbms_Output.put_line('records of the test_policy is '|| cnt);   
  21.          --call nested transaction   
  22.          P_Insert_Policy('2010042102''2');   
  23.          rollback;--rollback data for all transactions   
  24.          commit;--master transaction commit   
  25.          select count(1into cnt from Test_Policy;   
  26.          Dbms_Output.put_line('records of the test_policy is '|| cnt);   
  27.          rollback;               
  28.          select count(1into cnt from Test_Policy;   
  29.          Dbms_Output.put_line('records of the test_policy is '|| cnt);               
  30.     END TEST_PL_SQL_ENTRY;   

运行输出结果如下:

  • records of the test_policy is 1 –-主事务中的操作已经commit   
  • records of the test_policy is 1 –-主事务的操作对Nested transaction有影响。   
  • records of the test_policy is 2 –-Nested transaction 已经Commit   
  • records of the test_policy is 2 –-Nested transaction对主事务有影响。  

将上面的nested transaction的procedure修改一下,不进行commit:

  1. Procedure P_Insert_Policy(I_Policy_code T_contract_master.Policy_Code%type,    
  2.                                 I_Policy_type t_contract_master.policy_type%type) as    
  3.       cnt number :=0;   
  4.       begin   
  5.           select count(1into cnt from Test_Policy;   
  6.           Dbms_Output.put_line('records of the test_policy is '|| cnt);   
  7.           Insert into Test_Policy values(I_Policy_code, I_Policy_type);   
  8.           --commit;   
  9.       end P_Insert_Policy;  
  10.  
  11.       PROCEDURE TEST_PL_SQL_ENTRY(I_POL_ID IN VARCHAR2, O_SUCC_FLG OUT VARCHAR2) AS   
  12.       strSql varchar2(500);   
  13.       cnt number := 0;   
  14.       BEGIN   
  15.          delete from test_policy;   
  16.          commit;   
  17.          insert into test_policy values('2010042101''1');   
  18.          select count(1into cnt from Test_Policy;   
  19.          Dbms_Output.put_line('records of the test_policy is '|| cnt);   
  20.             
  21.          P_Insert_Policy('2010042102''2');   
  22.          rollback;   
  23.          commit;   
  24.          select count(1into cnt from Test_Policy;   
  25.          Dbms_Output.put_line('records of the test_policy is '|| cnt);   
  26.          rollback;   
  27.             
  28.          select count(1into cnt from Test_Policy;   
  29.          Dbms_Output.put_line('records of the test_policy is '|| cnt);   
  30.             
  31.     END TEST_PL_SQL_ENTRY;   

运行输出结果如下: 

  • records of the test_policy is 1 –-主事务中的操作已经commit   
  • records of the test_policy is 1 –-主事务的操作对Nested transaction有影响。   
  • records of the test_policy is 0 –-Nested transaction 的数据被主事务rollback.   
  • records of the test_policy is 0  

     

三、 自治事务

以下类型的 PL/SQL blocks 可以被定义为自治事务:

  • Stored procedures and functions.
  • Local procedures and functions defined in a PL/SQL declaration block.
  • Packaged procedures and functions.
  • Type methods.
  • Top-level anonymous blocks.

定义方法非常简单,在 DECLARE 后加上 PRAGMA AUTONOMOUS_TRANSACTION 即可。

来看一个简单的例子,注意以下在一个会话内执行

  1. CREATE TABLE at_test (
  2. id NUMBER NOT NULL,
  3. description VARCHAR2(50) NOT NULL
  4. );
  5. INSERT INTO at_test (id, description) VALUES (1, 'Description for 1');
  6. INSERT INTO at_test (id, description) VALUES (2, 'Description for 2');
  7. -- 不要提交
  8. SELECT * FROM at_test;
  9. ID DESCRIPTION
  10. ---------- --------------------------------------------------
  11. 1 Description for 1
  12. 2 Description for 2
  13. 2 rows selected.
  14. -- 自治事务plsql block
  15. DECLARE
  16. PRAGMA AUTONOMOUS_TRANSACTION;
  17. cnt number := 0;
  18. BEGIN
  19. select count(*) into cnt from at_test;
  20. Dbms_Output.put_line('cnt: '|| cnt); -- 输出0,因为自治事务不受主事务影响
  21. FOR i IN 3 .. 10 LOOP
  22. INSERT INTO at_test (id, description)
  23. VALUES (i, 'Description for ' || i);
  24. END LOOP;
  25. COMMIT;
  26. select count(*) into cnt from at_test;
  27. Dbms_Output.put_line('cnt: '|| cnt); -- 输出8,插入8行
  28. END;
  29. /
  30. -- 回到主事务查询,一共十行(提交的自治事务影响主事务)
  31. SELECT * FROM at_test;
  32. ID DESCRIPTION
  33. ---------- --------------------------------------------------
  34. 1 Description for 1
  35. 2 Description for 2
  36. 3 Description for 3
  37. 4 Description for 4
  38. 5 Description for 5
  39. 6 Description for 6
  40. 7 Description for 7
  41. 8 Description for 8
  42. 9 Description for 9
  43. 10 Description for 10
  44. 10 rows selected.
  45. -- 回滚,再查询,发现主事务插入的2行没了,自治事务插入的还在
  46. ROLLBACK;
  47. SELECT * FROM at_test;
  48. ID DESCRIPTION
  49. ---------- --------------------------------------------------
  50. 3 Description for 3
  51. 4 Description for 4
  52. 5 Description for 5
  53. 6 Description for 6
  54. 7 Description for 7
  55. 8 Description for 8
  56. 9 Description for 9
  57. 10 Description for 10
  58. 8 rows selected.

再看一个与前面嵌套事务对应的例子:

  1. create Procedure p_insert_policy_new(i_policy_code Varchar2(20), i_policy_type char(1)) as
  2. Pragma Autonomous_Transaction; --定义自治事务
  3. cnt number := 0;
  4. begin
  5. select count(1) into cnt from test_policy;
  6. Dbms_Output.put_line('records of the test policy table is: '||cnt);
  7. Insert into Test_Policy values(I_Policy_code, I_Policy_type);
  8. commit;
  9. select count(1) into cnt from test_policy;
  10. Dbms_Output.put_line('records of the test policy table is: '||cnt);
  11. end p_insert_policy_new;
  12. /
  13. --call auto trans procedure
  14. create PROCEDURE TEST_PL_SQL_ENTRY(I_POL_ID IN VARCHAR2, O_SUCC_FLG OUT VARCHAR2) AS
  15. strSql varchar2(500);
  16. cnt number := 0;
  17. v_policyCode t_contract_master.policy_code%type;
  18. BEGIN
  19. delete from test_policy;
  20. commit;
  21. insert into test_policy values('2010042101', '1');
  22. select count(1) into cnt from Test_Policy;
  23. Dbms_Output.put_line('records of the test_policy is '|| cnt);
  24. p_insert_policy_new('2010042102', '2');
  25. select count(1) into cnt from Test_Policy;
  26. Dbms_Output.put_line('records of the test_policy is '|| cnt);
  27. rollback;
  28. select policy_code into v_policyCode from test_policy;
  29. Dbms_Output.put_line('policy_code: '|| v_policyCode);
  30. select count(1) into cnt from Test_Policy;
  31. Dbms_Output.put_line('records of the test_policy is '|| cnt);
  32. END TEST_PL_SQL_ENTRY;
  33. /

运行结果如下:

  • records of the test_policy is 1 -- 主事务插入数据
  • records of the test policy table is: 0 -- 自治事务不受主事务影响
  • records of the test policy table is: 1 -- 自治事务提交
  • records of the test_policy is 2 -- 提交的自治事务影响主事务
  • policy_code: 2010042102 -- 主事务回滚,自治事务已提交数据不受影响
  • records of the test_policy is 1 -- 同上,行数为1

 

下面是一个用自治事务收集报错日志信息的例子:

定义一个自治事务存储过程

  1. CREATE OR REPLACE PROCEDURE log_errors (p_error_message IN VARCHAR2) AS
  2. PRAGMA AUTONOMOUS_TRANSACTION;
  3. BEGIN
  4. INSERT INTO error_logs (id, log_timestamp, error_message)
  5. VALUES (error_logs_seq.NEXTVAL, SYSTIMESTAMP, p_error_message);
  6. COMMIT;
  7. END;
  8. /

外层代码调用存储过程,报错时记录日志

  1. BEGIN
  2. INSERT INTO at_test (id, description) VALUES (998, 'Description for 998');
  3. -- Force invalid insert.
  4. INSERT INTO at_test (id, description) VALUES (999, NULL);
  5. EXCEPTION
  6. WHEN OTHERS THEN
  7. log_errors (p_error_message => SQLERRM);
  8. ROLLBACK;
  9. END;
  10. /
  11. SELECT * FROM at_test WHERE id >= 998;
  12. no rows selected
  13. SELECT * FROM error_logs;
  14. ID LOG_TIMESTAMP ERROR_MESSAGE
  15. ---------- ----------------------- -----------------------------------------------
  16. 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

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/盐析白兔/article/detail/509222
推荐阅读
相关标签
  

闽ICP备14008679号