Oracle 数据库维护管理之--dbms_lock

时间:2024-03-08 17:58:05

1、查询相关的v$视图,但是提示表或视图不存在解决办法
     原因是使用的用户没有相关的查询权限导致

     解决办法:

       grant select  any dictionary to 用户;    --这个权限比较大 

       grant select_catalog_role to 用户;  --这个权限是最低的要求,但是可以访问到v$相关视图

       收回权限  

       revoke select_catalog_role from 用户;

       结果:

 

2、其中我们需要登录sys或者system级别的用户才可以进行这方面的授权

     sys用户,默认的登录密码是change_on_install as sysdba

 3、我们可以使用dbms_lock进行多会话(多机)模式下,共享代码片段访问的控制。

--假设我们要控制访问的共享代码片段
create or replace function fun_wxc(p1 in varchar2
)
return number 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
  lock_name   varchar2(100):=\'fun_wxc_2\';
  lock_handle varchar2(100);
  lock_is_get number;
begin
  --打印会话信息
  dbms_output.put_line(\'--------------------->session start<---------------------\');
  --lockname 类似于定义一个资源的名称,用于并发控制程序判断当前这个资源有没有被锁定
  --产生锁
  dbms_lock.allocate_unique(lockname => lock_name, 
lockhandle => lock_handle); dbms_output.put_line(\'the lock handle is \' || lock_handle); dbms_output.put_line(\'lock request start time is \' ||to_char((sysdate), \'yyyy/mm/dd hh24:mi:ss\')); --请求锁,如果代码已经被执行(即公共代码正在被执行),锁请求等待p_lock_expired秒后超时退出 lock_is_get := dbms_lock.request(lock_handle, p_lock_mode, p_lock_expired, false); --判锁获取是否成功,不成功则不能执行公共代码块 if lock_is_get <> 0 then dbms_output.put_line(\'the procedure is executing,can not call it in the same time\'); end if;
--请求锁成功 if lock_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; lock_is_get := dbms_lock.release(lock_handle);--执行完成后释放锁 end if; end p_enqueue_test;

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

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

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

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

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

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

会话5以排他模式获取资源fun_wxc上的锁,因为锁模式与会话4产生的锁是不兼容的,所以可以被阻塞在等待者队列中,但是(经历会话1、2共25s+会话3共25s+会话4共25s=75s等待)等待超时了,所以因超时放弃执行(注意超时信息打印时间),如下时间所示

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

我们使用的查看锁脚本语句是:select * from v$lock;

可以看到,两个会话同时到达公共代码块的入口前一行代码进行锁的申请,由于我们手动启动是先启动会话1的,会话1取得了锁并且是排他锁,所以会话2处于等待状态,等待锁获取时间为10s,而会话1执行的时间是25s(使用系统睡眠函数进行模拟替代),最终在会话1释放锁之前,会话2因为请求锁超时而自动退出,会话1执行完公共代码块后,释放锁资源。

总结:在多会话的情境下,我们可以使用dbms_lock提供的锁机制控制并发执行。

文章参考:http://www.cnblogs.com/wangxingc/p/6179901.html#undefined