Oracle与SQL自治事务

自治事务

自治事务是独立的事务操作,如果考虑到事务回滚,必须单独写成一个触发器来完成,

一个事务A在另一个事务B内被调用,那个事务A是自治事务,自治事务A执行过程中会脱离其session内未执行完毕的事务的影响。

如果session从B事务开始——A事务开始和结束——B事务结束

上述的A事务不受没有完成的B事务的影响,然后A事务执行完毕后再次回到B事务执行没有完成的B事务。

通过pragma autonomous_transaction将一个pl/sql程序结构设定为自治事务,pragma是编译器指令,

1、自治事务使用情况

无法回滚的审计 : 一般情况下利用触发器禁止某些对表的更新等操作时,若记录日志,则触发器最后抛出异常时会造成日志回滚。利用自治事务可防止此点。
避免变异表: 即在触发器中操作触发此触发器的表
在触发器中使用ddl 写数据库:对数据库有写操作(insert、update、delete、create、alter、commit)的存储过程或函数是无法简单的用sql来调用的,此时可以将其设为自治事务,从而避免ora-14552(无法在一个查询或dml中执行ddl、commit、rollback)、ora-14551(无法在一个查询中执行dml操作)等错误。需要注意的是函数必须有返回值,但仅有in参数(不能有out或in/out参数)。 
开发更模块化的代码: 在大型开发中,自治事务可以将代码更加模块化,失败或成功时不会影响调用者的其它操作,代价是调用者失去了对此模块的控制,并且模块内部无法引用调用者未提交的数据。

2、Oracle 自制事务是指的存储过程和函数可以自己处理内部事务不受外部事务的影响,用pragma autonomous_transaction来声明,要创建一个自治事务,您必须在匿名块的最高层或者存储过程、函数、数据包或触发的定义部分中,使用PL/SQL中的PRAGMA AUTONOMOUS_TRANSACTION语句。在这样的模块或过程中执行的SQL语句都是自治的。

create or replace trigger TR_UPDT_TRIGGER
BEFORE UPDATE OF CURRENTSTATUS ON M_TABLE
FOR EACH ROW
DECLARE
e_count INTEGER;
e_sum NUMBER;
e_avg NUMBER;
PRAGMA AUTONOMOUS_TRANSACTION;
BEGIN
select avg(currentstatus) into e_avg
from m_businessentityextend where entityindex = :new.entityindex;
select sum(currentstatus) into e_sum
from m_businessentityextend where entityindex = :new.entityindex;
select count(currentstatus) into e_count
from m_businessentityextend where entityindex = :new.entityindex;

e_avg := (e_sum - :old.currentstatus + :new.currentstatus) / e_count;
update m_businessentity set entitystatus = (case when e_avg = 1 then 1 else 2 end) where entityindex = :new.entityindex;

COMMIT;
END;

create or replace procedure AutoNomouse_Insert is PRAGMA AUTONOMOUS_TRANSACTION; 
begin 
insert into Msg values('AutoNomouse Insert');   
commit;  
 end;

3、自治事务可以嵌套,嵌套深度等只受init.ora参数transactions(同时并发的事务数,缺省为sessions的1.1倍)制约。因为自治事务是与主事务(简称MT)相分离的,所以它不能检测到被修改过的行的当前状态。这就好像在主事务提交之前,它们一直处于单独的会话里,对自治事务来说,它们是不可用的。然而,反过来情况就不同了:主事务能够检测到已经执行过的自治事务的结果。

4、如果AT试图访问被MT控制的资源,可能有deadlock发生.Package 不能被声明为AT,只有package所拥有的function和procedure 才能声明为AT。主事务与自治事务是完全不同的事务,因此无法共享锁等。结束一个自治事务必须提交一个commit、rollback或执行ddl,否则会产生Oracle错误ORA-06519: active autonomous transaction detected and rolled back 。保存点无法在自治事务中回滚到父事务中的一个保存点,只能在内部使用保存点。

5、可能遇到的错误
ora-06519 – 检查到活动自治事务,回滚——退出自治事务时没有提交、回滚或ddl操作
ora-14450 – 试图访问正在使用的事务级临时表
ora-00060 – 等待资源时检查到死锁

SQL

USE [TABLE]
GO
EXEC sp_addlinkedserver @server = N'loopback' , @srvproduct = N' ' , @provider = N'SQLNCLI' , @datasrc = @@SERVERNAME
EXEC sp_serveroption loopback, N'rpc out' , 'TRUE'
EXEC sp_serveroption loopback, N'remote proc transaction promotion' , 'FALSE'
GO
BEGIN
IF (object_id('TR_UPDT_TEST_Pro', 'P') is not null)
drop proc TR_UPDT_TEST_Pro;
END
GO
CREATE proc TR_UPDT_TEST_Pro(@entityindex varchar(50),@newcurrentstatus int,@oldnewcurrentstatus int)
AS
BEGIN
DECLARE @e_count int,@e_sum numeric,@e_avg numeric;
select @e_avg=avg(currentstatus)
from m_businessentityextend where entityindex = @entityindex;
select @e_sum=sum(currentstatus)
from m_businessentityextend where entityindex = @entityindex;
select @e_count=count(currentstatus)
from m_businessentityextend where entityindex = @entityindex;
SET @e_avg= (@e_sum - @oldnewcurrentstatus + @oldnewcurrentstatus) / @e_count;
update m_businessentity set entitystatus = (case when @e_avg = 1 then 1 else 2 end) where entityindex =@entityindex;
END;
GO
BEGIN
IF (object_id('TR_UPDT_TRIGGER', 'tr') is not null)
DROP trigger TR_UPDT_TRIGGER
END;
GO
CREATE TRIGGER TR_UPDT_TRIGGER
ON M_TABLE
instead of UPDATE
AS
if update(CURRENTSTATUS)
BEGIN
DECLARE @entityindex varchar(32),@newcurrentstatus int,@oldnewcurrentstatus int;
select @entityindex=Inserted.entityindex,@newcurrentstatus=Inserted.currentstatus from Inserted;
select @oldnewcurrentstatus=deleted.currentstatus from deleted;
exec loopback. OSMP . dbo.TR_UPDT_TEST_Pro @entityindex,@newcurrentstatus,@oldnewcurrentstatus ;
END;
 以上脚本功能相同

参考链接:http://www.cnblogs.com/Ronger/archive/2012/02/15/2352527.html(摘抄)

http://blog.csdn.net/xman_78tom/article/details/5909124(模仿)

上一篇:AMQ学习笔记 - 14. 实践方案:基于ZooKeeper + ActiveMQ + replicatedLevelDB的主从部署


下一篇:c#打包文件解压缩