java如何清理当前游标_Oracle中清除游标缓存的几种方法

9i以后引入了bind peeking绑定变量窥视特性,但该特性常有帮当忙之嫌,所以有了11g的自适应游标特性。排除因绑定变量窥视造成的因素外,统计信息讹误也会造成执行计划偏差,这时我们就可能需要清除指定游标的缓存信息,从而达到重新解析的目的。

下面我们列举几种可以达到清除游标缓存的方法,权作抛砖引玉:

1. alter system flush shared_pool;              /* 最简单最粗暴的方法,清除所有游标缓存,可能造成短期内大量解析,不推荐*/

2. dbms_shared_pool 包很早就有了,但该包名下的purge过程却要到10.2.0.4才出现,Bug 5614566最早在2006年描述了需要清除游标缓存接口的要求:

Hdr: 5614566 10.2.0.2 RDBMS 10.2.0.2 DICTIONARY PRODID-5 PORTID-176

Abstract: WE NEED A FLUSH CURSOR INTERFACE

*** 10/20/06 07:48 am ***

而且该过程在10.2.0.4中默认是无法正常使用的,需要通过设置event 5614566或者打上5614566补丁来启用;具体设置方法如下:

alter system set events '5614566 trace name context forever';

该存储过程的具体argument如下:

PROCEDURE PURGE

参数名称 类型 输入/输出默认值?

------------------------------ ----------------------- ------ --------

NAME VARCHAR2 IN

FLAG CHAR IN DEFAULT

HEAPS NUMBER IN DEFAULT

其中NAME指定了需要清除的对象名,这里分成2种。PL/SQL对象,触发器,序列,类型和JAVA对象以其命名指定;SQL游标对象通过该SQL的address与hash_value组合指定。FLAG指定了对象的类型,若没有指定该参数,Oracle将认为之前代入的NAME参数对应到包/存储过程/函数的命名空间, 需要注意的是该参数是大小写敏感的,包括了以下各类型:

FLAG值

对应对象类型

P

包/存储过程/函数

Q

序列

R

触发器

T

类型

JS

Java源程序

JC

Java类程序

JR

Java资源

JD

Java共享数据

C

cursor

HEAP参数指定了清除对象的哪些堆信息,以SQL游标为例,其最主要的信息包括在HEAP 0和HEAP 6中,HEAP 0包括了游标自身的大多数信息,而HEAP 6则存放了游标相关的执行计划。如果我们想要清除HEAP 0和HEAP 6中的信息,则2的0次方+2的6次方=1+64=65,那么我们在代入HEAP参数为65 即可;如果我们只想清除游标的执行计划则清除HEAP 6即可,代入HEAP参数为2的6次方即64。该参数的默认值为1,清除HEAP 0将会导致整个对象的缓存信息被清除掉。

下面我们来演示如何利用该存储过程来清除SQL缓存:

SQL> alter system flush shared_pool;

系统已更改。

SQL> select /* cache_me */ count(*) from youyus;

COUNT(*)

----------

9

SQL> select sql_id,

2         address,

3         hash_value,

4         executions,

5         loads,

6         version_count,

7         invalidations,

8         parse_calls

9    from v$sqlarea

10   where sql_text like '%cache_me%'

11     and sql_text not like '%v$sqlarea%';

SQL_ID        ADDRESS  HASH_VALUE EXECUTIONS      LOADS VERSION_COUNT INVALIDATIONS PARSE_CALLS

------------- -------- ---------- ---------- ---------- ------------- ------------- -----------

25asu5a76nqmn 2F51508C 2389334644          3          1             1             0           3

SQL> select address, plan_hash_value

2    from v$sql_plan

3   where sql_id = '25asu5a76nqmn';

ADDRESS  PLAN_HASH_VALUE

-------- ---------------

2F51508C      2542806819

2F51508C      2542806819

2F51508C      2542806819

SQL> exec dbms_shared_pool.purge('2F51508C,2389334644','C',64);

PL/SQL 过程已成功完成。

SQL> select sql_id,

2 address,

3 hash_value,

4 executions,

5 loads,

6 version_count,

7 invalidations,

8 parse_calls,

9 plan_hash_value

10 from v$sqlarea

11 where sql_text like '%cache_me%'

12 and sql_text not like '%v$sqlarea%';

SQL_ID ADDRESS HASH_VALUE EXECUTIONS LOADS VERSION_COUNT INVALIDATIONS PARSE_CALLS PLAN_HASH_VALUE

------------- -------- ---------- ---------- ---------- ------------- ------------- ----------- ---------------

25asu5a76nqmn 2F51508C 2389334644 4 1 1 0 4 2542806819

SQL> select * from v$sql_plan where plan_hash_value= 2542806819;

未选定行

/*执行计划消失了,而游标主体信息仍在*/

SQL> select /* cache_me */  count(*)  from youyus;

COUNT(*)

----------

9

SQL> select sql_id,

2         address,

3         hash_value,

4         executions,

5         loads,

6         version_count,

7         invalidations,

8         parse_calls,

9         plan_hash_value

10    from v$sqlarea

11   where sql_text like '%cache_me%'

12     and sql_text not like '%v$sqlarea%';

SQL_ID        ADDRESS  HASH_VALUE EXECUTIONS      LOADS VERSION_COUNT INVALIDATIONS PARSE_CALLS PLAN_HASH_VALUE

------------- -------- ---------- ---------- ---------- ------------- ------------- ----------- ---------------

25asu5a76nqmn 2F51508C 2389334644          5          1             1             0           5      2542806819

/*这里新增的一次parse call是硬解析*/

SQL>  select address,operation from v$sql_plan where plan_hash_value= 2542806819;

ADDRESS  OPERATION

-------- ------------------------------------------------------------

2F51508C SELECT STATEMENT

2F51508C SORT

2F51508C TABLE ACCESS

SQL> exec dbms_shared_pool.purge('2F51508C,2389334644','C',1);

PL/SQL 过程已成功完成。

SQL> select sql_id,

2         address,

3         hash_value,

4         executions,

5         loads,

6         version_count,

7         invalidations,

8         parse_calls,

9         plan_hash_value

10    from v$sqlarea

11   where sql_text like '%cache_me%'

12     and sql_text not like '%v$sqlarea%';

未选定行

SQL> select address,operation from v$sql_plan where plan_hash_value= 2542806819;

未选定行

SQL> select /* cache_me */  count(*)  from youyus;

COUNT(*)

----------

9

SQL> select sql_id,

2         address,

3         hash_value,

4         executions,

5         loads,

6         version_count,

7         invalidations,

8         parse_calls,

9         plan_hash_value

10    from v$sqlarea

11   where sql_text like '%cache_me%'

12     and sql_text not like '%v$sqlarea%';

SQL_ID        ADDRESS  HASH_VALUE EXECUTIONS      LOADS VERSION_COUNT INVALIDATIONS PARSE_CALLS PLAN_HASH_VALUE

------------- -------- ---------- ---------- ---------- ------------- ------------- ----------- ---------------

25asu5a76nqmn 2F51508C 2389334644          1          2             1             1           1      2542806819

/*清除游标heap 0后,包括执行计划的所有信息都被清除了,甚至于simulator中的信息*/

3.如果您的环境中恰好无法利用dbms_shared_pool.purge存储过程,我们也可以采用一些折中的方法来清除游标缓存;譬如通过一个无关紧要的grant/revoke操作,但这样也会造成所有该授权/撤职对象相关SQL的执行计划失效:

SQL> alter system flush shared_pool;

系统已更改。

SQL> select /* cache_me */ count(*) from youyus;

COUNT(*)

----------

9

SQL> select sql_id,

2 address,

3 hash_value,

4 executions,

5 loads,

6 version_count,

7 invalidations,

8 parse_calls,

9 plan_hash_value

10 from v$sqlarea

11 where sql_text like '%cache_me%'

12 and sql_text not like '%v$sqlarea%';

SQL_ID ADDRESS HASH_VALUE EXECUTIONS LOADS VERSION_COUNT INVALIDATIONS PARSE_CALLS PLAN_HASH_VALUE

------------- -------- ---------- ---------- ---------- ------------- ------------- ----------- ---------------

25asu5a76nqmn 2F540EA0 2389334644 1 1 1 0 1 2542806819

SQL> select address,operation,to_char(timestamp,'HH24:MI:SS') from v$sql_plan where plan_hash_value= 2542806819;

ADDRESS OPERATION TO_CHAR(

-------- ------------------------------------------------------------ --------

2F540EA0 SELECT STATEMENT 13:39:28

2F540EA0 SORT 13:39:28

2F540EA0 TABLE ACCESS 13:39:28

SQL> revoke select on youyus from scott;

撤销成功。

SQL> select sql_id,

2 address,

3 hash_value,

4 executions,

5 loads,

6 version_count,

7 invalidations,

8 parse_calls,

9 plan_hash_value

10 from v$sqlarea

11 where sql_text like '%cache_me%'

12 and sql_text not like '%v$sqlarea%';

SQL_ID ADDRESS HASH_VALUE EXECUTIONS LOADS VERSION_COUNT INVALIDATIONS PARSE_CALLS PLAN_HASH_VALUE

------------- -------- ---------- ---------- ---------- ------------- ------------- ----------- ---------------

25asu5a76nqmn 2F540EA0 2389334644 1 1 1 1 1 2542806819

/*授权/撤销会造成执行计划invalid,此处 INVALIDATIONS上升到1*/

SQL> select /* cache_me */ count(*) from youyus;

COUNT(*)

----------

9

/*重新执行SQL,将引发一次硬解析*/

SQL> select address,operation,to_char(timestamp,'HH24:MI:SS') from v$sql_plan where plan_hash_value= 2542806819;

ADDRESS OPERATION TO_CHAR(

-------- ------------------------------------------------------------ --------

2F540EA0 SELECT STATEMENT 13:40:23

2F540EA0 SORT 13:40:23

2F540EA0 TABLE ACCESS 13:40:23

/*执行计划的时间戳发生了变化,达到了重新解析游标的目的*/

4.或许你不是一个位高权重的DBA,无法执行授权/撤职命令,但如果你能分析游标所涉及对象的统计信息或者执行其他一些ddl操作,那么也可以达到同样的目的:

SQL> alter system flush shared_pool;

系统已更改。

SQL>

SQL> select /* cache_me */ count(*) from youyus;

COUNT(*)

----------

9

SQL> select sql_id,

2 address,

3 hash_value,

4 executions,

5 loads,

6 version_count,

7 invalidations,

8 parse_calls,

9 plan_hash_value

10 from v$sqlarea

11 where sql_text like '%cache_me%'

12 and sql_text not like '%v$sqlarea%';

SQL_ID ADDRESS HASH_VALUE EXECUTIONS LOADS VERSION_COUNT INVALIDATIONS PARSE_CALLS PLAN_HASH_VALUE

------------- -------- ---------- ---------- ---------- ------------- ------------- ----------- ---------------

25asu5a76nqmn 2F540EA0 2389334644 1 1 1 0 1 2542806819

SQL> analyze table youyus compute statistics;

表已分析。

SQL> select sql_id,

2 address,

3 hash_value,

4 executions,

5 loads,

6 version_count,

7 invalidations,

8 parse_calls,

9 plan_hash_value

10 from v$sqlarea

11 where sql_text like '%cache_me%'

12 and sql_text not like '%v$sqlarea%';

SQL_ID ADDRESS HASH_VALUE EXECUTIONS LOADS VERSION_COUNT INVALIDATIONS PARSE_CALLS PLAN_HASH_VALUE

------------- -------- ---------- ---------- ---------- ------------- ------------- ----------- ---------------

25asu5a76nqmn 2F540EA0 2389334644 1 1 1 1 1 2542806819

/*统计信息更新,造成了invalid*/

SQL> create index ind_youyus on youyus(t1);

索引已创建。

SQL> alter system flush shared_pool;

系统已更改。

SQL> select /* cache_me */ count(*) from youyus;

COUNT(*)

----------

9

SQL> select sql_id,

2 address,

3 hash_value,

4 executions,

5 loads,

6 version_count,

7 invalidations,

8 parse_calls,

9 plan_hash_value

10 from v$sqlarea

11 where sql_text like '%cache_me%'

12 and sql_text not like '%v$sqlarea%';

SQL_ID ADDRESS HASH_VALUE EXECUTIONS LOADS VERSION_COUNT INVALIDATIONS PARSE_CALLS PLAN_HASH_VALUE

------------- -------- ---------- ---------- ---------- ------------- ------------- ----------- ---------------

25asu5a76nqmn 2F464EA0 2389334644 1 1 1 0 1 2542806819

SQL> alter index ind_youyus rebuild online;

索引已更改。

SQL> select sql_id,

2 address,

3 hash_value,

4 executions,

5 loads,

6 version_count,

7 invalidations,

8 parse_calls,

9 plan_hash_value

10 from v$sqlarea

11 where sql_text like '%cache_me%'

12 and sql_text not like '%v$sqlarea%';

SQL_ID ADDRESS HASH_VALUE EXECUTIONS LOADS VERSION_COUNT INVALIDATIONS PARSE_CALLS PLAN_HASH_VALUE

------------- -------- ---------- ---------- ---------- ------------- ------------- ----------- ---------------

25asu5a76nqmn 2F464EA0 2389334644 1 1 1 1 1 2542806819

/*在线重建索引也可以达到同样的目的*/

That's Great!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值