zoukankan      html  css  js  c++  java
  • ProcedureLevel Atomicity(存储过程级别的原子性:)

    网址:http://asktom.oracle.com/pls/asktom/f?p=100:11:0::NO::P11_QUESTION_ID:1270688200346183091

     异常的处理:http://asktom.oracle.com/pls/asktom/f?p=100:11:0::NO::P11_QUESTION_ID:1270688200346183091

    It is interesting to note that Oracle considers PL/SQL anonymous blocks to be statements as well. Consider the following stored procedure:

    注意:Oracle认为匿名的PL/SQL块也是语句。

    匿名PL/SQL块:

    DECLARE

    BEGIN

    NULL;

    END;

    考虑如下的存储过程:

    ops$tkyte@ORA10G> create or replace procedure p

      2  as

      3  begin

      4          insert into t values ( 1 );

      5          insert into t values (-1 );

      6  end;

      7  /

    Procedure created

     

    ops$tkyte@ORA10G> select * from t;

    no rows selected

     

    ops$tkyte@ORA10G> select * from t2;

     

           CNT

    ----------

             0

    So, we have a procedure we know will fail.(我们已经知道存储过程会失败的,因为为了测试!) The second INSERT will always fail in this  case. Let¿s see what happens if we run that stored procedure;第二个插入语句经常会失败,让我们检查,在运行存储过程的时候,到底发生了什么:

    ops$tkyte@ORA10G> begin

      2          p;

      3  end;

      4  /

    I fired and updated 1 rows

    I fired and updated 1 rows

    begin

    *

    ERROR at line 1:

    ORA-02290: check constraint (OPS$TKYTE.SYS_C009598) violated

    ORA-06512: at "OPS$TKYTE.P", line 5

    ORA-06512: at line 2

    ops$tkyte@ORA10G> select * from t;

    no rows selected

    ops$tkyte@ORA10G> select * from t2;

     

           CNT

    ----------

             0

    As you can see, Oracle treated the stored procedure call as an atomic statement. (认为存储过程的调用是一个原子性的语句),The client submitted a block of code, 客户端提供了一个原子性的语句块:(BEGIN P; END;, and Oracle wrapped a SAVEPOINT around it. Oracle在围绕他的地方分装了一个SAVEPOINT,Since P failed, Oracle restored the database back to the point right before it was called. Now, if we submit a slightly different block, we will get entirely different results:当调用P失败的时候,P会自动的修复到调用前的状态。如果我们使用一个稍微不同的语句块,我们将得到截然不同的运行结果。

    ops$tkyte@ORA10G> begin

      2      p;

      3  exception

      4      when others then null;

      5  end;

      6  /

    I fired and updated 1 rows

    I fired and updated 1 rows

     

    PL/SQL procedure successfully completed.

     

    ops$tkyte@ORA10G> select * from t;

             X

    ----------

             1

    ops$tkyte@ORA10G> select * from t2;

           CNT

    ----------

             1

    Here, we ran a block of code that ignored any and all errors, and the difference in outcome here is huge. 在这里,我们运行了一个语句块,它忽略了所有的错误信息,输出的结果差别非常的大;Whereas the first call to P effected no changes, here the first INSERT succeeds and the CNT column in T2 is incremented accordingly.

    我们在第一调用的时候,没有发生任何改变,但是在第二次调用的时候,两个表中都存在了值。

    Note I consider virtually all code that contains a WHEN OTHERS exception handler that does not also include a RAISE to re-raise the exception to be a bug. It silently ignores the error and it changes the transaction semantics. Catching WHEN OTHERS and translating the exception into an old-fashioned return code changes the way the database is supposed to behave.

     事实上,在含有WHEN OTHERS 的异常处理语句块,但是没有包含RAISE重新的抛出该异常信息的是一个BUG,它默默的忽略了错误,并且改变的事务的语义,使用WHEN OTHERS捕获,将异常信息转换为一个CODE返回。

    Oracle considered the statement to be the block that the client submitted. This statement succeeded by catching and ignoring the error itself, so the If error then rollback... didn¿t come into effect and Oracle did not roll back to the SAVEPOINT after execution. Hence, the partial work performed by P was preserved. The reason that this partial work was preserved in the first place is that we have statement-level atomicity within P: each statement in P is atomic. P becomes the client of Oracle when it submits its two INSERT statements. Each INSERT either entirely succeeds or fails. This is evidenced by the fact that we can see that the trigger on T fired twice and updated T2 twice, yet the count in T2 reflects only one UPDATE. The second INSERT executed in P had an implicit SAVEPOINT wrapped around it.

    Oracle认为CLIENT提交的语句是一个数据块,当捕获了这个语句抛出的异常,或者这个语句忽略了自身的异常,Oracle认为这个语句执行成功了。所以当出现错误信息的时候,回滚不会生效,Oracle在执行之后,也不会回滚到检查点

    (因为捕捉了异常,就默认认为语句执行成功,既然语句执行成功,根本不会触发ROLLBACK),因此,存储过程P执行的局部的代码产生的结果将会保留,由于在存储过程P中,我们含有语句级的原子性,在P中的每一个语句都是原子性的,P变成了一个CLIENT,他提交了两个INSERT语句,每一个语句要么成功,要么失败,它们之间不会相互的影响---------,事实表明了这样子

    The difference between the two blocks of code is subtle, and something you must consider in your applications. Adding an exception handler to a block of PL/SQL code can radically change its behavior. A different way to code this¿one that restores the statement-level atomicity to the entire PL/SQL block¿is as follows:

    ops$tkyte@ORA10G> begin

      2      savepoint sp;

      3      p;

      4  exception

      5      when others then

      6          rollback to sp;

      7  end;

      8  /

    I fired and updated 1 rows

    I fired and updated 1 rows

     

    PL/SQL procedure successfully completed.

    ops$tkyte@ORA10G> select * from t;

    no rows selected

    ops$tkyte@ORA10G> select * from t2;

           CNT

    ----------

             0

    一般的异常处理逻辑应该是:

     

    begin

       savepoint X;

       p;

    exception

     

    when others then

      rollback to X;

      RAISE;

    end;

     

     

     

     

    http://asktom.oracle.com/pls/asktom/f?p=100:11:0::NO::P11_QUESTION_ID:1270688200346183091

  • 相关阅读:
    有耗介质中波的传播
    介质分界处的反射
    TFSF边界条件
    吸收边界条件
    .apk的MIME类型
    Java instanceof
    Java toString()方法的自动调用
    整理一系列优秀的Android开发源码
    GOOGLE CODE ANDROID 开源项目 集合
    imsdroid 学习(初认识)
  • 原文地址:https://www.cnblogs.com/caroline/p/2717694.html
Copyright © 2011-2022 走看看