您的位置:首页 > 数据库 > Oracle

oracle 事务原子性

2013-08-17 15:54 375 查看
事务会把数据库从一种一致状态转变为另一种一致状态。事务主要有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编程艺术。。。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: