oracle 多版本机制,关于oracle多版本机制副作用的问题-Oracle

我们已经知道oracle多版本机制能够提供一致性的答案,而且还有高度的并发性。但是真的就没有其他不好的一面吗?

案例1:

假设有一个资源调度程序(可以用来调度会议室,投影仪等资源),业务规则是:在给定的时间段不能将一种资源分配给多人。这里涉及到资源表(Resources)与资源调度表(Secludes)。

我们一般的实现方式是,先查询某一时间段的某一资源是否已经被分配,如果没有被分配,我们就可以使用。

查看是否被分配SQL语句:

select count(*)  from schedules where resource_name = :room_name

and (start_time <= :new_end_time)  and (end_time >= :new_start_time)。  —SQL1

然后插入分配记录(如果得到结果为0)  www.2cto.com

insert into schedules ( resource_name, start_time, end_time )

values  ( p_resource_name, p_start_time, p_end_time );   —SQL2

但是如果我们让2个人同时预定13:00到14:00期间的投影仪资源,可能都会预定成功。假设一个人是事务A,另外一个人是事务B,在事务A执行SQL1语句的时候,事务B也开始执行SQL1语句(因为oracle里面查询是不会被阻塞的)。那么事务A与事务B查询的结果都是0,于是都可以申请到投影仪资源了。

解决方案:

应该在查询之前先锁定要申请的资源,使得事务A与事务B在执行SQL1与SQL2语句的时候串行。

在执行SQL1语句之前先执行如下SQL语句:

select * from resources where resource_name = :room_name FOR UPDATE;  —SQL3

这样当事务A执行完SQL3之后,事务B执行SQL3的时候就会被阻塞。除非事务B申请资源跟事务A不同。

案例2:热表上超出期望的I/O

在生产环境中在一个大负载条件下,一个查询使用的 I/O 比你在测试或开发系统时观察到的 I/O 要多得多。造成这种现象的原因是:在你测试系统中,由于它是独立的,所以不必撤销事务修改。不过,在生产系统中,读一个给定的块时,可能必须撤销(回滚)多个事务所做的修改,而且每个回滚都可能涉及I/O来获取undo信息并应用于系统。

因为oracle提供多版本机制的原理是,读取数据的时候判断这个数据是不是已经被修改了,如果被修改了就从undo段去获取修改前的数据。如果发现这个修改前的数据还不是想要的数据,继续找更老的数据,直到找到开始执行SQL语句那一刻这个数据的值。

所以在oracle里面如果一个表经常被修改,查询,会发生这样的情况。因为查询的时候,如果被修改的数据越多,需要读取undo段的信息就越长,I/O操作自然也会越多。对于这种热表的查询,最好能够把查询的时间压缩到最短,以便在查询期间,这个数据被其他事务修改的概率最低,从而需要从undo段读取的数据最少,最大限度减少I/O操作的概率。

作者 liwenshui322

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值