oracle事务嵌套研究
2008-04-29 10:17
696 查看
[align=left]l 事务嵌套测试案例[/align]
[align=left](1)首先,建立一个表:[/align]
[align=left]create table msg (msg varchar2(100));[/align]
[align=left](2)然后,建立子事务存储过程local。[/align]
create or replace procedure local is
cnt number := -1; -- Global variables
begin
select count(*) into cnt from msg;
dbms_output.put_line('local: # of rows is '||cnt);
insert into msg values ('New Record');
commit;
end;
(3)最后,用如下PL/SQL匿名块调用local;
declare
cnt number := -1;
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;
[align=left]运行结果(注意打开set serveroutput on)如下:[/align]
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-> 主匿名块最后’看到’了所有的记录.
PL/SQL 过程已成功完成。
(4)重建过程local,将commit改为rollback,如下:
create or replace procedure local is
cnt number := -1; -- Global variables
begin
select count(*) into cnt from msg;
dbms_output.put_line('local: # of rows is '||cnt);
insert into msg values ('New Record');
rollback;
end;
执行第(3)步的PL/SQL匿名块,
[align=left]运行结果(注意打开set serveroutput on)如下:[/align]
local: # of rows is 1
main: # of rows is 0-> 子程序把主匿名块的一条记录也rollback了,所以结果为0
local: # of rows is 0
local: # of rows is 1-> 主匿名块把自己的一条记录成功commt,子程序也可以看到
main: # of rows is 1
PL/SQL 过程已成功完成。
(5)重建过程local,将commit去掉,如下:
create or replace procedure local is
cnt number := -1; -- Global variables
begin
select count(*) into cnt from msg;
dbms_output.put_line('local: # of rows is '||cnt);
insert into msg values ('New Record');
end;
执行第(3)步的PL/SQL匿名块,
[align=left]运行结果(注意打开set serveroutput on)如下:[/align]
local: # of rows is 1-> 子程序看到主匿名块uncommited的一条记录
main: # of rows is 2-> 主匿名块可以看到主匿名块和子程序插入的uncommited记录
local: # of rows is 0-> 主匿名块把主匿名块和子程序插入的记录全部rollback
local: # of rows is 2-> 主匿名块把主匿名块和子程序插入的记录全部commit
main: # of rows is 3
PL/SQL 过程已成功完成。
l AUTONOMOUS TRANSACTION(自治事务)的介绍
AUTONOMOUS_TRANSACTION是指在function,procedure等subprograms中对事务进行自治管理,当在别的pl/sql block里去调用这些subprograms的时候这些subprograms并不随着父pl/sql block的失败而回滚,而是自己管自己commit。自治事务常用于写入LOG或TRAC信息便于查找错误。
自治事务(以下简称AT)是由主事务(以下简称MT)调用但是独立于MT的事务。在自治事务被调用执行时,MT被挂起,在自治事务内部,一系列的DML可以被执行并且commit或rollback. 自治事务防止嵌套提交,使事务在自己的事务区内提交或回滚不会影响其他的事务。由于自治事务的独立性,它的commit和rollback并不影响MT的执行效果。在自治事务执行结束后,主事务获得控制权,又可以继续执行了。
[align=left]实现自治事务的定义,只需下列PL/SQL的声明部分加上PRAGMA AUTONOMOUS_TRANSACTION 就可以了。[/align]
[align=left]1. 顶级的匿名PL/SQL块[/align]
[align=left]2. Functions 或 Procedure[/align]
[align=left]3. 触发器。[/align]
[align=left]比如:[/align]
[align=left]在一个独立的procedure中声明自治事务:[/align]
[align=left]CREATE OR REPLACE PROCEDURE [/align]
[align=left] Log_error(error_msg IN VARCHAR2(100))[/align]
[align=left]IS[/align]
[align=left] PRAGMA AUTONOMOUS_TRANSACTION;[/align]
[align=left]BEGIN[/align]
[align=left] Insert into Error_log values ( sysdate,error_msg);[/align]
[align=left] COMMIT;[/align]
[align=left]END;[/align]
现在用自治事务改写一下procedure local:
create or replace procedure local is
cnt number := -1; -- Global variables
PRAGMA AUTONOMOUS_TRANSACTION;
begin
select count(*) into cnt from msg;
dbms_output.put_line('local: # of rows is '||cnt);
insert into msg values ('New Record');
commit;
end;
执行第(3)步的PL/SQL匿名块,
[align=left]运行结果(注意打开set serveroutput on)如下:[/align]
local: # of rows is 0 -> 子事务local中无法’看到’主匿名块中的uncommitted记录 (因为它是独立的)
main: # of rows is 2-> 主匿名块可以’看到’2条记录,但只有一条是被commited.
local: # of rows is 1 -> 子事务local中可以’看到’它前一次commit的记录,但是主匿名块中的记录已经被提前rollback了
local: # of rows is 3 -> 子事务local 中可以’看到’3条记录包括主匿名块commit的记录
main: # of rows is 4 ->主匿名块最后’看到’了所有的记录.
PL/SQL 过程已成功完成。
l 结论:
从这个例子中我们看到,在没有自制事务的情况下,COMMIT和ROLLBACK的位置无论是在主匿名块中或者在子程序中,都会影响到整个当前事务. 如果子程序中有事务或有commit语句,那么是回滚不了的,否则可以回滚,因为事务只是回滚上一个committ或rollback之后的所有事务。
在使用自制事务的情况下, AT是独立的,在它执行时,MT被暂停了. AT的COMMIT,ROLLBACK并不影响MT的执行.
[align=left]运用AT时,有一些注意事项,简单列举如下:[/align]
[align=left]1. 在匿名PL/SQL块中,只有顶级的匿名PL/SQL块可以被设为AT[/align]
[align=left]2. Package 不能被声明为AT,只有package所拥有的function和procedure 才能声明为AT[/align]
[align=left]3. AT程序必须以commit 或rollback结尾,否则会产生Oracle错误ORA-06519: active autonomous transaction detected and rolled back[/align]
[align=left](1)首先,建立一个表:[/align]
[align=left]create table msg (msg varchar2(100));[/align]
[align=left](2)然后,建立子事务存储过程local。[/align]
create or replace procedure local is
cnt number := -1; -- Global variables
begin
select count(*) into cnt from msg;
dbms_output.put_line('local: # of rows is '||cnt);
insert into msg values ('New Record');
commit;
end;
(3)最后,用如下PL/SQL匿名块调用local;
declare
cnt number := -1;
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;
[align=left]运行结果(注意打开set serveroutput on)如下:[/align]
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-> 主匿名块最后’看到’了所有的记录.
PL/SQL 过程已成功完成。
(4)重建过程local,将commit改为rollback,如下:
create or replace procedure local is
cnt number := -1; -- Global variables
begin
select count(*) into cnt from msg;
dbms_output.put_line('local: # of rows is '||cnt);
insert into msg values ('New Record');
rollback;
end;
执行第(3)步的PL/SQL匿名块,
[align=left]运行结果(注意打开set serveroutput on)如下:[/align]
local: # of rows is 1
main: # of rows is 0-> 子程序把主匿名块的一条记录也rollback了,所以结果为0
local: # of rows is 0
local: # of rows is 1-> 主匿名块把自己的一条记录成功commt,子程序也可以看到
main: # of rows is 1
PL/SQL 过程已成功完成。
(5)重建过程local,将commit去掉,如下:
create or replace procedure local is
cnt number := -1; -- Global variables
begin
select count(*) into cnt from msg;
dbms_output.put_line('local: # of rows is '||cnt);
insert into msg values ('New Record');
end;
执行第(3)步的PL/SQL匿名块,
[align=left]运行结果(注意打开set serveroutput on)如下:[/align]
local: # of rows is 1-> 子程序看到主匿名块uncommited的一条记录
main: # of rows is 2-> 主匿名块可以看到主匿名块和子程序插入的uncommited记录
local: # of rows is 0-> 主匿名块把主匿名块和子程序插入的记录全部rollback
local: # of rows is 2-> 主匿名块把主匿名块和子程序插入的记录全部commit
main: # of rows is 3
PL/SQL 过程已成功完成。
l AUTONOMOUS TRANSACTION(自治事务)的介绍
AUTONOMOUS_TRANSACTION是指在function,procedure等subprograms中对事务进行自治管理,当在别的pl/sql block里去调用这些subprograms的时候这些subprograms并不随着父pl/sql block的失败而回滚,而是自己管自己commit。自治事务常用于写入LOG或TRAC信息便于查找错误。
自治事务(以下简称AT)是由主事务(以下简称MT)调用但是独立于MT的事务。在自治事务被调用执行时,MT被挂起,在自治事务内部,一系列的DML可以被执行并且commit或rollback. 自治事务防止嵌套提交,使事务在自己的事务区内提交或回滚不会影响其他的事务。由于自治事务的独立性,它的commit和rollback并不影响MT的执行效果。在自治事务执行结束后,主事务获得控制权,又可以继续执行了。
[align=left]实现自治事务的定义,只需下列PL/SQL的声明部分加上PRAGMA AUTONOMOUS_TRANSACTION 就可以了。[/align]
[align=left]1. 顶级的匿名PL/SQL块[/align]
[align=left]2. Functions 或 Procedure[/align]
[align=left]3. 触发器。[/align]
[align=left]比如:[/align]
[align=left]在一个独立的procedure中声明自治事务:[/align]
[align=left]CREATE OR REPLACE PROCEDURE [/align]
[align=left] Log_error(error_msg IN VARCHAR2(100))[/align]
[align=left]IS[/align]
[align=left] PRAGMA AUTONOMOUS_TRANSACTION;[/align]
[align=left]BEGIN[/align]
[align=left] Insert into Error_log values ( sysdate,error_msg);[/align]
[align=left] COMMIT;[/align]
[align=left]END;[/align]
现在用自治事务改写一下procedure local:
create or replace procedure local is
cnt number := -1; -- Global variables
PRAGMA AUTONOMOUS_TRANSACTION;
begin
select count(*) into cnt from msg;
dbms_output.put_line('local: # of rows is '||cnt);
insert into msg values ('New Record');
commit;
end;
执行第(3)步的PL/SQL匿名块,
[align=left]运行结果(注意打开set serveroutput on)如下:[/align]
local: # of rows is 0 -> 子事务local中无法’看到’主匿名块中的uncommitted记录 (因为它是独立的)
main: # of rows is 2-> 主匿名块可以’看到’2条记录,但只有一条是被commited.
local: # of rows is 1 -> 子事务local中可以’看到’它前一次commit的记录,但是主匿名块中的记录已经被提前rollback了
local: # of rows is 3 -> 子事务local 中可以’看到’3条记录包括主匿名块commit的记录
main: # of rows is 4 ->主匿名块最后’看到’了所有的记录.
PL/SQL 过程已成功完成。
l 结论:
从这个例子中我们看到,在没有自制事务的情况下,COMMIT和ROLLBACK的位置无论是在主匿名块中或者在子程序中,都会影响到整个当前事务. 如果子程序中有事务或有commit语句,那么是回滚不了的,否则可以回滚,因为事务只是回滚上一个committ或rollback之后的所有事务。
在使用自制事务的情况下, AT是独立的,在它执行时,MT被暂停了. AT的COMMIT,ROLLBACK并不影响MT的执行.
[align=left]运用AT时,有一些注意事项,简单列举如下:[/align]
[align=left]1. 在匿名PL/SQL块中,只有顶级的匿名PL/SQL块可以被设为AT[/align]
[align=left]2. Package 不能被声明为AT,只有package所拥有的function和procedure 才能声明为AT[/align]
[align=left]3. AT程序必须以commit 或rollback结尾,否则会产生Oracle错误ORA-06519: active autonomous transaction detected and rolled back[/align]
相关文章推荐
- Oracle数据库为了数据的完整性的嵌套事务调用的研究
- 存储过程的嵌套事务研究
- Oracle 嵌套事务与自治事务思考
- Oracle嵌套事务(Nested Transaction)与自治事务(Autonomous Transaction)详解
- [导入]Sqlserver和Oracle混合事务
- Oracle的自治事务
- Oracle的实体化视图(MVIEW)的深入研究之三
- Spring JDBC-事务方法嵌套调用解读
- oracle-SQL语言基础-事务控制命令命令
- 数据库事务与隔离级别示例(oracle与sql server对比)
- Oracle 性能测试一:嵌套SQL的查询速度比较分析(初级)
- 关于分布式事务、两阶段提交、一阶段提交、Best Efforts 1PC模式和事务补偿机制的研究
- Oracle(二) – 事务控制解释
- Oracle回滚机制深入研究
- Spring声明式事务管理及事务嵌套
- ORACLE 之 事务(ONE)
- 《Oracle 9i&10g 编程艺术》读书笔记——事务
- oracle 合并查询 事务 sql函数小知识学习
- Oracle事务与函数