将指定SQL的执行计划从共享池删除的方法(二)

2014-11-24 08:33:32 ? 作者: ? 浏览: 8
-------------
gr7s3j0cg8pr6 00000000B6A5A470 418666214 2 1 2 0
ak90gdq0udv37 00000000B6E3C6B0 2175200359 2 2 2 1
对于其他用户而言,都可以使用将表的查询权限授权给OWNER本身的方法,但是测试用户本身为SYS,因此需要其他用户授权,方便起见使用了授权给PUBLIC的方式。可以看到,这种方式同样可以生效,但是仍然存在打击面过大的问题。对于系统中一个频繁访问的表,很可能这个授权的操作,导致少则几十,多则几百个SQL都是失效,这个风险仍然不可小觑。
那么对于就没有一个可以将粒度控制在SQL本身上的方法吗?在11g中, Oracle的DBMS_SHARED_POOL包新增了PURGE功能,可以完美的解决这个问题,这个方法在10.2.0.4和10.2.0.5补丁集中也被添加进来,使得10.2的高版本同样可以实现这个功能,使用方法很简单:
SQL> select count(*) from dual;
COUNT(*)
----------
1
SQL> select sql_id, address, hash_value, executions, loads, parse_calls, invalidations
2 from v$sqlarea
3 where sql_text = 'select count(*) from dual';
SQL_ID ADDRESS HASH_VALUE EXECUTIONS LOADS PARSE_CALLS INVALIDATIONS
------------- ---------------- ---------- ---------- ---------- ----------- -------------
4m94ckmu16f9k 00000000B6C61FC0 4094900530 1 2 1 1
SQL> select 1 from dual;
1
----------
1
SQL> select * from dual;
D
-
X
SQL> select sql_id, address, hash_value, executions, loads, parse_calls, invalidations
2 from v$sqlarea www.2cto.com
3 where lower(sql_text) like '%dual%';
SQL_ID ADDRESS HASH_VALUE EXECUTIONS LOADS PARSE_CALLS INVALIDATIONS
------------- ---------------- ---------- ---------- ---------- ----------- -------------
gr7s3j0cg8pr6 00000000B6A5A470 418666214 3 1 3 0
520mkxqpf15q8 00000000B6DD9610 2866845384 1 2 1 1
ak90gdq0udv37 00000000B6E3C6B0 2175200359 3 2 3 1
4m94ckmu16f9k 00000000B6C61FC0 4094900530 1 2 1 1
a5ks9fhw2v9s1 00000000B698DA88 942515969 1 2 1 1
SQL> exec dbms_shared_pool.purge('00000000B6C61FC0,4094900530', 'c')
PL/SQL procedure successfully completed.
SQL> select sql_id, address, hash_value, executions, loads, parse_calls, invalidations
2 from v$sqlarea
3 where lower(sql_text) like '%dual%';
SQL_ID ADDRESS HASH_VALUE EXECUTIONS LOADS PARSE_CALLS INVALIDATIONS
------------- ---------------- ---------- ---------- ---------- ----------- -------------
gr7s3j0cg8pr6 00000000B6A5A470 418666214 4 1 4 0
520mkxqpf15q8 00000000B6DD9610 2866845384 1 2 1 1
ak90gdq0udv37 00000000B6E3C6B0 2175200359 3 2 3 1
a5ks9fhw2v9s1 00000000B698DA88 942515969 1 2 1 1
过程PURGE的第一个参数为V$SQLAREA中用逗号分隔的ADDRESS列和HASH_VALUE列的值,第二个参数’c’表示PURGE的对象是CURSOR,不过实际上这里可以使用除了P(PROCEDURE/FUNCTION/PACKAGE)、T(TYPE)、R(TRIGGER)和Q(SEQUENCE)的任何值 www.2cto.com
使用这种方法,就可以精确的将一个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_POOL的PURGE才可以生效。也就是说,除非提前进行过设置,否则这个PURGE的功能对于一个产品环境而言,必须在10.2.0.5以上版本才可以使用。
作者 yangtingkun
-->

评论

帐  号: 密码: (新用户注册)
验 证 码:
表  情:
内  容: