《Oracle编程艺术》学习笔记(15)-事务原子性 .

事务的四大特性:ACID
· 原子性(atomicity):事务中的所有动作要么都发生,要么都不发生。
· 一致性(consistency):事务将数据库从一种一致状态转变为下一种一致状态。
· 隔离性(isolation):一个事务的影响在该事务提交前对其他事务都不可见。
· 持久性(durability):事务一旦提交,其结果就是永久性的。

语句级原子性
下面的insert语句,如果由于check约束而失败,显而易见就不会插入数据。
create table t(x int check(x > 0));
insert into t values(-1);

下面在T上创建触发器,触发器中更新表格T2的cnt列,这个时候如果由于约束而插入失败了,T2会被更新吗?
create table t2 ( cnt int );
insert into t2 values ( 0 );
commit;

create trigger t_trigger
before insert or delete on t for each row
begin
   if ( inserting ) then
        update t2 set cnt = cnt +1;
   else
        update t2 set cnt = cnt -1;
   end if;
   dbms_output.put_line( 'I fired and updated '  || sql%rowcount || ' rows' );
end;
/

insert into t values(-1);

select * from t2;

可以看到结果是:
       CNT
----------
         0

在Oracle中,语句级原子性可以根据需要延伸。在前面的例子中,如果INSERT INTO T 触发了一个触发器,这个触发器会更新另一个表,而那个表也有一个触发器,它会删除第三个表(以此类推),那么要么所有工作都成功,要么无一成功。

过程级原子性
Oracle把PL/SQL匿名块也当作是语句,也具有原子性。可以通过下面试验证明。
首先创建过程,
create or replace procedure p
as
begin
        insert into t values ( 1 );
        insert into t values (-1 );
end;
/
然后执行下面语句,
begin
    insert into t values ( 2 );
    p;
end;
/

下面查询T和T2,可以看到上面的3条插入语句全部没有效果。
Oracle在我们的代码块外面包了1个SAVEPOINT,如果代码块的执行失败了,Oracle将数据库恢复到调用这个代码块之前的时间点。
但是如果修改了存储过程P,
create or replace procedure p
as
begin
        insert into t values ( 1 );
        insert into t values (-1 );
exception
 when others then
            dbms_output.put_line( 'Error!!!! ' || sqlerrm );
end;
/
再来执行下面的代码块
begin
    insert into t values ( 2 );
    p;
end;
/
就会发现插入2和1的操作成功了。
Oracle把客户提交的代码块认为是“语句”。这个语句之所以会成功,因为它自行捕获并忽略了错误。

实际上,如果代码中包含一个WHEN OTHERS异常处理器,而不包括RAISE或者RAISE_APPLICATION_ERROR来重新抛出这个异常,可以认为这样的代码都是有bug的。
Oracle11g之后,如果代码中包含上述情况,PL/SQL编译的时候会产生1个Warning。
alter session set PLSQL_Warnings = 'enable:all';
然后执行上面的create or replace procedure p...语句,然后调用show errors

tony@ORA11GR2>  show errors procedure p;
PROCEDURE P 出现错误:

LINE/COL ERROR
-------- -----------------------------------------------------------------
1/1      PLW-05018: 单元 P 省略了可选的 AUTHID 子句; 使用默认值 DEFINER
7/7      PLW-06009: 过程 "P" OTHERS 处理程序并未在 RAISE 或
         RAISE_APPLICATION_ERROR 中终止

需要注意的是,过程级原子性依靠的是PL/SQL例程本身不完成任何提交或者回滚,
可以认为,在PL/SQL过程中执行COMMIT和ROLLBACK是一个不好的编程实践。只有PL/SQL的调用者才知道事务何时应该完成。

来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/11980046/viewspace-736077/,如需转载,请注明出处,否则将追究法律责任。

转载于:http://blog.itpub.net/11980046/viewspace-736077/

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值