通过dbms_lock了解oracle内部enqueue机制

同时被调用的共享代码如下

create or replace function fun_wxc(p1 in varchar2)
return number-- result_cache 
is
  rs number;
begin
  rs := p1;
  sys.dbms_lock.sleep(25);
  return rs;
end;

锁代码如下

create or replace procedure p_enqueue_test(p_lock_mode/*请求获取的锁模式*/    number,
                                           p_lock_expired/*请求等待超时时间*/ number) is
  l_name   varchar2(100);
  l_handle varchar2(100);
  l_is_get number;
  f_name   varchar2(240) := 'fun_wxc';--要调用代码片段的名称
  p_p1     number := 2;
begin
  --打印会话信息
  dbms_output.put_line('--------------------->session' ||testseq.nextval||'<---------------------');
   /*lockname 类似于定义一个资源的名称,用于并发控制程序判断当前这个资源有没有被锁定*/
  l_name := f_name || '_' || p_p1;
  dbms_lock.allocate_unique(lockname => l_name, lockhandle => l_handle);
  dbms_output.put_line('the lock handle is ' || l_handle);
  dbms_output.put_line('lock request start time is ' ||
                       to_char((sysdate), 'yyyy/mm/dd hh24:mi:ss'));
  --锁请求,若果代码已经被执行,锁请求等待xx s后超时退出
  l_is_get := dbms_lock.request(l_handle,
                                p_lock_mode,
                                p_lock_expired,
                                false);
  --判锁获取是否成功,不成功则不执行我们的代码
  if l_is_get <> 0 then
    dbms_output.put_line('the procedure is executing,can not call it in the same time');
  end if;
  if l_is_get = 0 then
    dbms_output.put_line('the lock request seccuss,execute start time is ' ||
                         to_char((sysdate), 'yyyy/mm/dd hh24:mi:ss'));
    -----------------------------------------------------------------
    /*要执行的代码开始*/
    declare
      r1 number;
    begin
      r1 := fun_wxc(2);
    /*要执行的代码结束*/
      dbms_output.put_line('the procedure has been executed,finish time is ' ||
                           to_char((sysdate), 'yyyy/mm/dd hh24:mi:ss'));
    end;
    --执行完成后释放锁
    l_is_get := dbms_lock.release(l_handle);
  end if;
end;

同时开5个sqlplus 窗口,模拟5个并发会话要同时执行函数fun_wxc的场景

开始后5个会话依次完成,结果如下

会话1以共享模式获取资源fun_wxc上的锁,成功

会话2以共享模式获取资源fun_wxc上的锁,因为锁模式是兼容的,所以可以成功获取,并且与会话1几乎同时完成,如下时间所示

会话3以排他模式获取资源fun_wxc上的锁,因为锁模式是不兼容的,所以可以被阻塞在等待者队列中,到会话1,2完成后释放资源,最终获取到了锁资源并且成功执行,如下时间所示

会话4以共享模式获取资源fun_wxc上的锁,因为锁模式是不兼容的,所以可以被阻塞在等待者队列中,到会话3完成后释放资源,最终获取到了锁资源并且成功执行,如下时间所示

会话5以排他模式获取资源fun_wxc上的锁,因为锁模式是不兼容的,所以可以被阻塞在等待者队列中,但是等待超时了,所以没有执行如下时间所示

在v$lock 并中也可以监控到执行时候的排队情况,如下

 

posted on 2016-12-14 16:39  wangxingc  阅读(584)  评论(0编辑  收藏  举报

导航