oracle事务_笔记1:过程级原子性
过程级原子性
有意思的是,Oracle把PL/SQL匿名块也当做是语句。
scott@ORCL>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.
scott@ORCL>delete from t;
0 rows deleted.
scott@ORCL>update t2 set cnt=0;
1 row updated.
scott@ORCL>select * from t;
no rows selected
scott@ORCL>select * from t2;
CNT
----------
0
以上创建了一个过程,而且我们知道这个过程不会成功。在这个过程中,第二个INSERT总会失败,下面来看运行这个存储过程时会发生什么情况:
scott@ORCL>begin
2 p;
3 end;
4 /
I fired and updated1rows
I fired and updated1rows
begin
*
ERROR at line 1:
ORA-02290: check constraint (SCOTT.SYS_C0013626) violated
ORA-06512: at "SCOTT.P", line 5
ORA-06512: at line 2
scott@ORCL>select * from t;
no rows selected
scott@ORCL>select * from t2;
CNT
----------
0
可以看到,Oracle把这个存储过程调用处理为一个原子语句。客户提交了一个代码块BEGIN P;END;,Oracle在它外面包了一个SAVEPOINT。由于P失败了,Oracle将数据库恢复到调用这个存储过程之前的时间点。
现在,如果提交一个稍微不同的代码块,会得到完全不同的结果:
scott@ORCL>begin
2 p;
3 exception
4 when others then
5 dbms_output.put_line('Error!' || sqlerrm);
6 end;
7 /
I fired and updated1rows
I fired and updated1rows
Error!ORA-02290: check constraint (SCOTT.SYS_C0013626) violated
PL/SQL procedure successfully completed.
scott@ORCL>select * from t;
X
----------
1
scott@ORCL>select * from t2;
CNT
----------
1
scott@ORCL>rollback;
Rollback complete.
在此,我们运行的代码块会忽略所有错误,这两个代码块的输出结果有显著的差别。尽管前面第一个P调用没有带来任何改变,但在这里的P调用中,第一个INSERT会成功,而且T2中的CNT列会相应地递增。
Oracle认为客户提交的代码块是“语句”。这个语句之所以会成功,因为它自行捕获并忽略了错误,所以If error then rollback...没有起作用,而且执行这个语句后Oracle没有回滚到SAVEPOINT。因此,这就保留了P完成的部分工作。为什么会保留这一部分工作呢?首要的原因是P中有语句级原子性:P中的每条语句都具有原子性。P提交其两条INSERT语句时就成为Oracle的客户。每个INSERT要么完全成功,要么完全失败。可以看到,T上的触发器触发了两次,而且将T2更新了两次,不过T2中的计数只反映了一个UPDATE。P中执行的第二个INSERT外包着一个隐式的SAVEPOINT。
本文来源 我爱IT技术网 http://www.52ij.com/jishu/5233.html 转载请保留链接。
- 评论列表(网友评论仅供网友表达个人看法,并不表明本站同意其观点或证实其描述)
-
