-自治事务

 
Oracle 笔记 - 自治事务
IT168 服务器学院】 15 自治事务
   DECLARE
   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 等待资源时检查到死锁
 
 
 
 
 
 
 
Oracle 中使用自治事务保存日志表条目
 
数据库事务是一种单元操作,要么是全部操作都成功,要么全部失败。在Oracle中,一个事务是从执行第一个数据管理语言(DML)语句开始,直到执行一个COMMIT语句,提交保存这个事务,或者执行一个ROLLBACK语句,放弃此次操作结束。
事务的“要么全部完成,要么什么都没完成”的本性会使将错误信息记入数据库表中变得很困难,因为当事务失败重新运行时,用来编写日志条目的INSERT语句还未完成。
针对这种困境,Oracle提供了一种便捷的方法,即自治事务。自治事务从当前事务开始,在其自身的语境中执行。它们能独立地被提交或重新运行,而不影响正在运行的事务。正因为这样,它们成了编写错误日志表格的理想形式。在事务中检测到错误时,您可以在错误日志表格中插入一行并提交它,然后在不丢失这次插入的情况下回滚主事务。
因为自治事务是与主事务相分离的,所以它不能检测到被修改过的行的当前状态。这就好像在主事务提交之前,它们一直处于单独的会话里,对自治事务来说,它们是不可用的。然而,反过来情况就不同了:主事务能够检测到已经执行过的自治事务的结果。
要创建一个自治事务,您必须在匿名块的最高层或者存储过程、函数、数据包或触发的定义部分中,使用PL/SQL中的PRAGMA AUTONOMOUS_TRANSACTION语句。在这样的模块或过程中执行的SQL Server语句都是自治的。
触发无法包含COMMIT语句,除非有PRAGMA AUTONOMOUS_TRANSACTION标记。但是,只有触发中的语句才能被提交,主事务则不行。
列表A展示了对一个简单但灵活的错误日志表格所作的CREATE TABLE和CREATE SEQUENCE语句。
CREATE TABLE errorlog (
    errorlog_id   NUMBER,
    logged_on     TIMESTAMP   DEFAULT SYSTIMESTAMP,
    logged_by     VARCHAR2(30)      DEFAULT USER,
    num1          NUMBER,
    num2          NUMBER,
    num3          NUMBER,
    text1         VARCHAR2(1000),
    text2         VARCHAR2(1000),
    text3         VARCHAR2(1000)
 );
 
CREATE SEQUENCE errorlog_seq
    START WITH 1
    INCREMENT BY 1;
列表B是一个独立的存储过程,用于更新错误日志表格。
CREATE OR REPLACE
PROCEDURE log_error (
   n1 IN NUMBER:=NULL, t1 IN VARCHAR:=NULL,
   n2 IN NUMBER:=NULL, t2 IN VARCHAR:=NULL,
   n3 IN NUMBER:=NULL, t3 IN VARCHAR:=NULL
   )
IS
 
   PRAGMA AUTONOMOUS_TRANSACTION;
 
BEGIN
 
   INSERT INTO errorlog
      (errorlog_id,
       num1, num2, num3, text1, text2, text3)
  VALUES
      (errorlog_seq.NEXTVAL, n1, n2, n3, t1, t2, t3);
 
   COMMIT;
 
END;
该过程接受最多三个数字和三个文本变量,然后将它们和时间戳以及调用过程的用户一起储存在表格中。
要测试这个过程,就要更新(UPDATE)或删除(DELETE)表格中的某些行;这就引发了主事务。然后执行存储过程,将您选择的要记入日志的数据传递给它。最后,重新运行主事务,选择(SELECT)错误日志表格,您的日志条目仍会在那儿。
(T114)
 
 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值