zoukankan      html  css  js  c++  java
  • 通过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 并中也可以监控到执行时候的排队情况,如下

  • 相关阅读:
    Android studio ButterKnife插件
    Android Studio Prettify 插件
    Android studio的主题颜色修改
    MeasureSpec 的三中类型
    android 加载远程Jar、APK
    android源码 键盘消息处理机制
    Android源码阅读笔记二 消息处理机制
    phpstrom 激活
    sublime vue 语法高亮插件安装
    mysql登录报错“Access denied for user 'root'@'localhost' (using password: YES”的处理方法
  • 原文地址:https://www.cnblogs.com/wangxingc/p/6179901.html
Copyright © 2011-2022 走看看