ORACLE HANDBOOK系列之七:事务(Transaction)

1概述

 

(在一个会话中)事务何时开始:当数据库遇到第一个DMLUPDATE/INSERT/DELETE/MERGE语句。 

(在一个会话中)事务何时结束:结束于第一个COMMIT/ROLLBACK/DDL/GRANT/REVOKE。对于DLL/GRANT/REVOKE,这些命令的内部嵌套了一个COMMIT语句。

上面的两句话是基本教义,就好比88耻之于和谐社会一样重要。

 

2事务级与语句级

CREATE TABLE t_trans_sample(fnum NUMBER(3));

 

insert into t_trans_sample values(1);       --sql-1
insert into t_trans_sample values(2);       --sql-2

 

根据教义,sql-1sql-2属于同一事务,此时如果我们执行commit/rollback,两条语句将同时被提交/回滚,即‘事务级’提交/回滚。

如果是这样呢:

 

insert into t_trans_sample values(1);       --sql-1
insert into t_trans_sample values(‘a’);    --sql-2

 

sql-2出错,此时只有出错的语句被回滚(当然受该语句影响的可能是多行数据),sql-1仍然处于未提交状态,即语句级回滚。

总结一下:用户显式执行的提交/回滚,通常总是‘事务级’的;当语句出错时由Oracle自动执行的回滚,通常总是‘语句级’的。

 

3隐式保存点

 

insert into t_trans_sample values(1);              --sql-1
begin
insert into t_trans_sample values(2);           --sql-2
insert into t_trans_sample values(‘a’);       --sql-3
end;

 

此时的结果是sql-2也被自动回滚了,只剩下sql-1的结果处于未提交状态。为什么,不是说应该是语句级的么?这是因为,执行PL/SQL匿名块、或者调用存储过程,会在紧挨着调用之前插入一个隐式的savepoint,当块内部出错并自动回滚时,并非是语句级的,而是回滚到此savepoint为止


但是,如果语句块中有
exception处理模块:

 

insert into t_trans_sample values(1);              --sql-1
begin
insert into t_trans_sample values(2);           --sql-2
insert into t_trans_sample values(‘a’);       --sql-3
exception
   
when others then
    
null;
end;

 

此时只有sql-3被回滚,sql-1sql-2仍处于未提交状态。


还有一点需要注意,
savepoint只针对回滚的情况,对于提交操作无影响,下面示例中的commit会将三条结果都提交:

 

insert into t_trans_sample values(1);              --sql-1
begin
insert into t_trans_sample values(2);           --sql-2
insert into t_trans_sample values(3);           --sql-3
commit;
end;

 

 

4触发器与事务

触发器代码中不允许发出任何事务控制语句,触发器与触发该触发器的SQL语句同属于一个事务,它只能随着外部事务的提交/回滚而提交/回滚。如果触发器内的DML(如果有的话)出错,则此DML被回滚,同时引发此触发器的DML也将被回滚。

(但在oracle8i 以及更高的版本中,你可以创建作为自治事务而执行的触发器,在这种情况下,触发器可以做提交或回滚操作,而与触发该触发器的外部SQL所在的事务无关,自治事务见后文)

 

5 Db link与事务

Oracle可以透明地处理分布式事务,意思就是,即便一个事务中涉及的表可能位于不同的oracle server上(通过Db link进行访问),对事务本身没有任何影响。这里就不作示例测试了。

 

6自治事务

普通的事务是无法进行嵌套的,例如你有一个大事务涉及10DML,你想先commit中间的3条是无法实现的。自治事务的出现很好地解决了这个问题,它可以使嵌套中的事务保持各自的独立,对比下面两个例子:

1

 

insert into t_trans_sample values(1);
begin
     
insert into t_trans_sample values(2);
     
commit;
end;
/

 

2

 

insert into t_trans_sample values(1);
declare
     pragma autonomous_transaction;
begin
     
insert into t_trans_sample values(2);
     
commit;
end;
/

 

1)中两条语句都被提交,这在前面的文章里已经提过了,(2)中只有第二个insert语句被提交,第一个仍然处于未提交的状态,可以看到自治事务的效果。在实际应用中,自治事务常常用于记录错误日志,通常来说,记录错误日志的事务应该独立出来,不应该与主事务杂揉在一起,这种情况下就应该使用自治事务了。

 

posted @ 2011-06-08 17:15  Morven.Huang  阅读(833)  评论(0编辑  收藏  举报