oracle事务一致性:原子性
原子性
事务的动作要么一起成功,要么都不成功,这是事务的原子性。
原子性包括:
- 语句级原子性
- 过程级原子性
- 事务级原子性
- DDL与原子性
语句级原子性
如果某条语句(如insert、update)执行成功与否会自动控制事务。
如设置插入前的触发器。
create table t2(cnt int);
insert into t2 values(0);
commit;
create table t(x int check(x>0));
create trigger t_tragger
before insert or update on t for each row
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 updateed '|| sql%rowcount||'rows');
end;
由于 表t设置了值约束,当插入负数的时候,是不能插入的
insert into t values(1);
此时 表t2中的cnt=1
如果
insert into t values(-1);
会报ora-02290违反检查约束条件
此时去检查表t2的cnt值没有更新成2,仍然是1.
书《oracle编程艺术》中sqlserver需要显式执行触发器的回滚才能实现触发器的不执行,但是我测试的是可以的。
create table t1 (cnt int)
create table t (v int check(v>0))
create trigger t_tragger
on t
for insert
as
begin
update t1 set cnt=cnt+1;
end
insert into t1 values(0)
select * from t1
insert into t values(-1)
过程级原子性
测试在存储过程中往表t中插入负数,会不会触发触发器的更新操作
create or replace procedure p
as
begin
insert into t values(1);
insert into t values(-1);
end;
当执行
begin
p;
end;
会报ora02290错误
表t 、t2不会插入和更新任何值
如果加入异常判断
begin
p;
exception
when others then
dbms_output.put_line('error'|| sqlerrm);
-- raise_application_error(-20001,sqlerrm);
end;
在when others then中
没有对错误抛出处理,只是进行了打印,
那么再执行时不会报错。
此时查询表t/t2会发现值被更新了一次。
这是因为存储过程中的每个Insert语句进行了事务提交,第二句sql因为不满足约束信息,跳转到when others then却没有执行异常处理,就回滚了。但是第一句sql没有回滚,被提交了。
begin
p;
exception
when others then
--dbms_output.put_line('error'|| sqlerrm);
raise_application_error(-20001,sqlerrm);
end;
这个时候保证了存储中必须全部执行完成后,才能提交事务。
所以在when others then 中必须加上raise 或者raise_application_error的处理,要不然语句的原子性会导致结果的提交,不能保证整个过程的原子性!
事务级原子性
一组SQL语句作为一个工作单元一同执行。数据库从一种一致状态转变为另一种一致状态。
DDL原子性
在oralce中执行DDL操作会导致事务的自动提交
尤其注意的是truncate table会导致事务提交。
但在sqlserver中可以在事务中创建临时表,不会导致事务提交。
上一篇: oracle查询锁参考
下一篇: mysql事务不加锁一致性读
推荐阅读