22、library cache_2(keep包、library cache的lock和pin、清空sql/执行计划、flush shared_pool)

有两个包:

1、DBMS_SHARED_POOL.KEEP,DBMS_SHARED_POOL包里有一个存储过程KEEP
2、DBMS_SHARED_POOL.PURGE,有一个存储过程PURGE

这两个包什么含义,怎么用?

1、DBMS_SHARED_POOL.KEEP:什么时候用KEEP呢?
oracle有一个问题,就是要执行包里面的某一个存储过程或者函数的时候,会把整个包调到library cache里面去,这时候,free里面的chunk很小(小碎片),这时候就会报ORA-04031错误,它会提示在加载哪个包的时候出现问题,如果经常出现这个问题,我们就有必要把这个package提前把它keep进library里去,让它缓存在library cache里,防止出问题;
碰到ORA-04031错误的时候,还有另外一个解决方案:shared pool里面专门有一个保留区;第一,把这个保留区做大一些; 第二,把进入保留区的这个size(门槛)降低一些

2、DBMS_SHARED_POOL.PURGE:
有时候,我们希望清空一下SQL以及执行计划,因为这个SQL比较差,希望系统重新解析一下,这时候就使用DBMS_SHARED_POOL.PURGE这个包

ORA-04031错误怎么出现的(经验值):
1、硬解析多:小、碎的free chunk
2、突然来了一个需要比较大的空间的package或者sql:需要空间大,还需要全部加载

查询包或者SQL是否被keep:

select * from v$db_object_cache

查看在library cache里面缓存着什么:

select distinct namespace from v$db_object_cache;  -- 这个SQL不要在生产里面跑,很危险

KEEP一个包:

查询包:

select * from v$db_object_cache where namespace='BODY';

首先执行一个脚本,把DBMS_SHARED_POOL.KEEP生成一下:

SQL> @?/rdbms/admin/dbmspool.sql
Package created.

Grant succeeded.

KEEP包:

SQL> exec dbms_shared_pool.keep('DBMS_SYSTEM','P')
PL/SQL procedure successfully completed.

再次查询:

select * from v$db_object_cache where namespace='BODY';

KEEP一个SQL:

查询SQL:

select * from v$sqlarea;

KEEP SQL:

SQL> exec dbms_shared_pool.keep('0000000064CB4510,2269249538','C')  --这个大写的C可以随便写,只要不是P、T、R、Q就行
-- 0000000064CB4510:ADDRESS
-- 2269249538:      HASH_VALUE

清空一下SQL以及执行计划

有时候,我们希望清空一下SQL以及执行计划,因为这个SQL比较差,希望系统重新解析一下
1、清空一个SQL以及他的执行计划:希望一个SQL重新解析一下
2、还有就是,一个packge占用的空间很大,但是执行次数很少,也清一下

如何清空一个SQL呢?

begin
DBMS_SHARED_POOL.PURGE('000000008A8AD1A8,1372979452','C');
end;
-- 000000008A8AD1A8:SQL对应的address
-- 1372979452:      SQL对应的hash值

清空整个shared pool:

SQL> alter system flush shared_pool;
System altered.

建议:一个一个去清,不要一次性清空

oracle的MOS网站:

https://support.oracle.com

library cache里面的lock和pin

模拟library cache的lock和pin:
1、建立一个存储过程(session 1里):

SQL> create or replace procedure p0001 as
begin
   dbms_lock.sleep(1000);
end;
/
Procedure created.

然后执行这个存储过程:

SQL> exec p0001;  -- 一直正在执行着

查询会话:

select * from v$session where username='SYS' and status='ACTIVE';

查询正在执行的SQL:

select * from v$sql where sql_id='2kf3164ugb2vz';

查询锁:

select event,v.SECONDS_IN_WAIT,v.WAIT_TIME from v$session v where username='SYS' and status='ACTIVE'and sid=20;


这里是手工加了一个锁

2、然后在session 2里,去编译session 1正在执行的(也就是加一个X锁):

SQL> alter procedure p0001 compile;

查询锁(session 2加不上X锁):

select event,v.SECONDS_IN_WAIT,v.WAIT_TIME from v$session v where username='SYS' and status='ACTIVE'and sid!=20;

3、在session 3里再执行一次:

SQL> exec p0001;

查询锁(加不上lock):

select event,v.SECONDS_IN_WAIT,v.WAIT_TIME from v$session v where username='SYS' and status='ACTIVE'and sid!=20;

4、在session 4里再执行一次:

SQL> exec p0001;

查询锁(加不上lock):

select event,v.SECONDS_IN_WAIT,v.WAIT_TIME from v$session v where username='SYS' and status='ACTIVE'and sid!=20;

只有第一个是pin,之后的都是lock锁

注意:lock和pin,lock是解决依赖关系的;pin是执行的瞬间pin住,解决对某一个对象执行的瞬间并发
在生产里面,特别的害怕:
1、ddl(DDL会导致表、视图里所依赖的一连串的存储过程要重新编译);
2、procedure

查询依赖关系:

select * from dba_dependencies

查询包的依赖关系:

select * from dba_dependencies s where s.referenced_type='VIEW' and type='PACKAGE';

posted @ 2024-11-21 15:25  一只c小凶许  阅读(0)  评论(0编辑  收藏  举报