dbms_shared_pool.purge 及其他几种使cursor失效的方法

DBMS_SHARED_POOL.PURGE 如何让游标cursor失效,如何清除占用共享池过大的游标:
http://blog.csdn.net/jiujiuaiqi/article/details/6825622
让已存在的CURSOR失效的方法:
1、在收集统计时,加no_invalidate => false参数:
2、整个刷新share pool
3、对这个表做ddl操作或授权都可以。
4.对表做一些DDL操作,比如create index 。
5.使用dbms_shared_pool.purge 包对sql执行cursor 刷出。


在日常管理中,经常有让sql重新解析的需求,比如说使用了bind peeking,第一次绑定特定值的时候执行计划走的特别糟,因为绑定变量导致之后的语句不作重新解析,重用了最差的执行计划,这时候我们希望重新解析来得到一个相对好的执行计划,常见的方法有:


a.alter system flush shared_pool;

b.对sql语句中的对象做个ddl,对sql语句中的对象做个ddl操作,涉及比较广,其中添加注释的commmet语句,也属于ddl语句,对生产库影响微乎其微。
语法:comment on table t1 is 'test table of bind peeking';

c.重新收集统计信息;
d.但是这些操作的影响都比较大(除了b点d的commemts之外),因此oracle在10.2.0.4后提供了个dbms_shared_pool.purge的方法,能够将某个sql的shared  cursor从共享池中清除,这样只会对单个sql产生影响.

Syntax:

DBMS_SHARED_POOL.PURGE (
   name         VARCHAR2,
   flag         CHAR DEFAULT 'P',
   heaps        NUMBER DEFAULT 1);

DBMS_SHARED_POOL.PURGE (
   schema       VARCHAR2,
   objname      VARCHAR2,
   namespace    NUMBER,
   heaps        NUMBER);
 
DBMS_SHARED_POOL.PURGE (
   hash         VARCHAR2,
   namespace    NUMBER,
   heaps        NUMBER);

 

测试:

10.2.0.4:

 

SQL> create table test(id int);

表已创建。

SQL> select * from test;

未选定行

SQL> select address,hash_value,executions,parse_calls from v$sql where sql_TEXT like 'select * from test%';

ADDRESS          HASH_VALUE EXECUTIONS PARSE_CALLS

---------------- ---------- ---------- -----------
0000040229F039E0 1689401402          1           1


QL> exec dbms_shared_pool.purge('0000040229F039E0,1689401402','C');

PL/SQL 过程已成功完成。

    过程PURGE的第一个参数为V$SQLAREA中用逗号分隔的ADDRESS列和HASH_VALUE列的值,第二个参数’c’表示PURGE的对象是CURSOR,不过实际上这里可以使用除了PPROCEDURE/FUNCTION/PACKAGE)、TTYPE)、RTRIGGER)和QSEQUENCE)的任何值

使用这种方法,就可以精确的将一个SQL从共享池中删除,从而使得Oracle为这个SQL重新生成执行计划。这种方法只针对单个SQL语句,使得解决问题的同时不会造成任何的误伤。

不过需要注意一点,在10.2.0.4中,虽然PURGE过程已经存在,但是要使这个过程可以真正的生效,还必须设置一个EVENT

SQL> alter system set event = '5614566 trace name context forever' scope = spfile;

System altered.

设置EVENT后需要重启,DBMS_SHARED_POOLPURGE才可以生效。也就是说,除非提前进行过设置,否则这个PURGE的功能对于一个产品环境而言,必须在10.2.0.5以上版本才可以使用。


验证查询如下:


SQL> select address,hash_value,executions,parse_calls from v$sql where sql_TEXT like 'select * from test%';

ADDRESS          HASH_VALUE EXECUTIONS PARSE_CALLS
---------------- ---------- ---------- -----------
0000040229F039E0 1689401402          1           1

 

可以看到purge并没有成功,为了进一步证实,再做一遍查询

 

SQL> select * from test;

未选定行

SQL> select address,hash_value,executions,parse_calls from v$sql where sql_TEXT like 'select * from test%';

ADDRESS          HASH_VALUE EXECUTIONS PARSE_CALLS
---------------- ---------- ---------- -----------
0000040229F039E0 1689401402          2           2

 

executions和parse_calls增加,说明前面的parse确实没生效

 

SQL> alter session set events '5614566 trace name context forever';

会话已更改。

SQL> exec dbms_shared_pool.purge('0000040229F039E0,1689401402','C');

PL/SQL 过程已成功完成。

SQL> select address,hash_value,executions,parse_calls from v$sql where sql_TEXT like 'select * from test%';

未选定行

 

参考 metalink Doc ID:  751876.1  
10.2.0.4默认不开启,要靠event 5614566或者补丁5614566来激活

 

11g:

 

11g>create table test_purge(id int);

 

11g>select * from test_purge;

 

11g>select address,hash_value from v$sql where sql_text like 'select * from test%';

HASH_VALUE
---------
3683003671

11g>exec dbms_shared_pool.purge('215E2F78,3683003671','C');

PL/SQL 过程已成功完成。

11g>select address,hash_value from v$sql where sql_text like 'select * from test%';

完成!!!




请使用浏览器的分享功能分享到微信等