oracle 事务原子性

事务会把数据库从一种一致状态转变为另一种一致状态。事务主要有ACID特性,其具体的内容如下:

  • 原子性(atomicity):事务中的所有动作要么都发生,要么都不发生。

  • 一致性(consistency): 事务将数据库从一种一致性状态转变为下一种一致状态。

  • 隔离性(isolation): 事务之间不会相互影响,事务之间是不可见的。

  • 持久性(durability):事务一旦提交,其结果是永久的。

oracle 事务控制语句:

  • commit: commit操作可以结束事务,并且使任何操作都持久化。

  • rollback: rollback操作可以结束事务,并且回滚任何你没有提交的操作。

  • savepoint: savepoint 可以建立一个‘marked point’在一个事务中,你可以在一个事务中设置多个savepoint。

  • rollback to savepoint: 回滚savepoint之后的操作。 

oracle事务的原子性:oracle的原子性分为语句级原子性,过程级原子性,事务级原子性。

 

语句级原子性: 先看kyte的例子

SQL> create table t2(cnt int);  

表已创建。  

SQL> insert into t2 values(0);  

已创建 1 行。  

SQL> create table t( x int check(x>0));  

表已创建。

 

create or replace trigger t_trigger  
  before INSERT OR DELETE on t  
  for each row  
declare
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 update '|| SQL%ROWCOUNT || 'rows');     
end t_trigger;

 

SQL> insert into t values(1);  
I fired and update 1rows  

已创建 1 行。 
SQL> insert into t values(-1);  
I fired and update 1rows  
insert into t values(-1)  
*  
第 1 行出现错误:  
ORA-02290: 违反检查约束条件 (SCOTT.SYS_C0015680)

可以看到插入时触发了触发器,在第二个语法中,即使插入错误,也触发了触发器,那么t2 表中是不是应该有两条数据,但是,在oracle看来,从insert语句开始,就是一个事务,事务要么全做,要么不做,所以在oracle中,当插入失败时,触发器中语句也会回滚。结果如下,可以看到,t2表中的数据是1。

SQL> select *from t2;  

       CNT  
----------  
         1

以上语句oracle的过程如下:oracle 在每个语句外面加了一个savepoint,当事务出错时,oracle就会回滚到事务的开始点。

SAVEPOINT statement1:  
  INSERT INTO VALUES(1);  
IF ERROR THEN ROLLBACK TO statment1;  
SAVEPOINT statement2;  
  INSERT INTO VALUES(-1);  
IF ERROR THEN ROLLBACK TO statment2;

过程级原子性 

    在oracle中pl/sql块被看做一个事务,也就是说被看做一个语句。看以下的例子

SQL> CREATE OR REPLACE PROCEDURE p  
  2  AS
  3  BEGIN
  4    INSERT INTO t VALUES(1);  
  5    INSERT INTO t VALUES(-1);  
  6  END;  
  7  /  

过程已创建。  
 
SQL> select *from t;  

未选定行  

SQL> select * from t2;  

       CNT  
----------  
         0

 下面我们执行这个存储过程,我们使用匿名块的执行方法 

SQL> begin
  2  p; 
  3  end; 
  4  / 
I fired and update 1rows 
I fired and update 1rows 
begin
* 
第 1 行出现错误: 
ORA-02290: 违反检查约束条件 (SCOTT.SYS_C0015680) 
ORA-06512: 在 "SCOTT.P", line 5 
ORA-06512: 在 line 2 

SQL> select *from t; 

未选定行 

SQL> select *from t2; 

       CNT 
---------- 
         0

 可以看到oracle把这个存储过程调用作为一个原子语句。相当于在begin前面加了savepoint,当失败时,oracle恢复到开始的那个savepoint。

现在我们对过程做以下处理

SQL> begin
  2  p; 
  3  exception 
  4  when others then null; 
  5  end; 
  6  / 
I fired and update 1rows 
I fired and update 1rows 

PL/SQL 过程已成功完成。 

SQL> select *from t; 

         X 
---------- 
         1 
SQL> select *from t2; 

       CNT 
---------- 
         1

可以看到,当我们忽略所有的错误时,这两个代码块的输出结果又显著的差别。 ,造成这个的原因就是,我们忽略了错误,所以if error then rollback 没有起作用,而过程中语句有原子性,所以oracle会执行成功其中一条语句。要恢复原子性,可以使用以下语句。

SQL> BEGIN
  2    SAVEPOINT SP; 
  3    P; 
  4  EXCEPTION 
  5    WHEN OTHERS THEN
  6      ROLLBACK TO SP; 
  7  END; 
  8  / 
I fired and update 1rows 
I fired and update 1rows 

PL/SQL 过程已成功完成。 

SQL> select * from t; 

未选定行 

SQL> select * from t2; 

       CNT 
---------- 
         0

事务级原子性

   事务是数据库从一种一致性状态转变为另一种一致状态,为了实现这个目标,事务也有原子性,事务完成的所有工作要么完全提交并成为永久性,要么完全回滚。像语句一样,事务是一个原子性的工作单元。

关于事务的原子性的学习总结到此为止,oracle如何在并发环境中提供隔离性,以后再做总结。

 

参照 Thomas kyte Orace 9i&10g编程艺术。。。

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值