oracle事务_笔记1:原子性语句级原子性
原子性
语句级原子性
Insert into t values(1);
看上去很明显,如果该语句由于一个约束冲突而失败,这一行就不会插入。
再考虑下面的例子,这里表T上的一个INSERT或DELETE会触发一个触发器,它将适当地调整表T2中的CNT列:
scott@ORCL>create table t2(cnt int);
Table created.
scott@ORCL>insert into t2 values(0);
1 row created.
scott@ORCL>commit;
Commit complete.
scott@ORCL>create table t(x int check(x>0));
Table created.
scott@ORCL>create trigger t_trigger
2 before insert or delete on t for each row
3 begin
4 if (inserting) then
5 update t2 set cnt=cnt +1;
6 else
7 update t2 set cnt=cnt -1;
8 end if;
9 dbms_output.put_line('I fired and updated' || sql%rowcount || 'rows');
10 end;
11 /
Trigger created.
在这种情况下,会发生什么就不那么显而易见了。如果触发器被触发,并且更新了T2,但是这一行没有插入到T中,结果会是什么?显然答案应该是,如果并没有真正在T中插入一行,我们就不希望T2中的CNT列递增。幸运的是,在Oracle中,客户最初发出的语句会完全成功或完全失败。这个语句是原子性的。
scott@ORCL>set serveroutput on
scott@ORCL>insert into t values(1);
I fired and updated1rows
1 row created.
scott@ORCL>insert into t values(-1);
I fired and updated1rows
insert into t values(-1)
*
ERROR at line 1:
ORA-02290: check constraint (SCOTT.SYS_C0013626) violated
scott@ORCL>select * from t2;
CNT
----------
1
这样一来,T中成功地插入一行,而且我们也及时地接收到消息:。下一个INSERT语句违反了T上的完整性约束。此时出现了DBMS_OUTPUT消息——T上的触发器确实触发了,这个DBMS_OUTPUT消息就是证据。触发器成功地完成了T2的更新。我们可能认为现在T2中的CNT的值是2,但是可以看到它的值实际上为1。Oracle保证最初的INSERT(即导致触发器触发的插入语句)是原子性的,这个INSERT INTO T是语句,所以INSERT INTO T的任何连带效果都被认为是该语句的一部分。
为了得到这种语句级原子性,Oracle悄悄地在每个数据库调用外面包了一个SAVEPOINT。前面两个INSERT实际上处理如下:
savepoint statement1;
insert into t values(1);
if error then rollback to statement1;
savepoint statement2;
insert into t values(-1);
if error then rollback to statement2;
在Oracle中,这种语句级原子性可以根据需要延伸。为保证这一点,无需编写任何特殊的代码,Oracle本来就会这么做。
本文来源 我爱IT技术网 http://www.52ij.com/jishu/5232.html 转载请保留链接。
- 评论列表(网友评论仅供网友表达个人看法,并不表明本站同意其观点或证实其描述)
-
