处理和解决游标独享/更高的版本支持如下:
Oracle Server - Enterprise Edition
这篇文章使用于一些平台
目的
解决问题指南用于帮助解决SQL共享问题。如果有可能,检测工具被包含在文档中用于帮助解决问题。
最后审核时间
January 15, 2009
读者说明
解决问题指南用于解决具体的错误。如果有可能,诊断工具被包含在文档中用于解决故障。
故障详情
1. 什么是SQL共享?
要记住的第一件事是所有的SQL都是隐含共享的。当一条SQL语句进入,关系数据库管理系统(RDBMS)将创建一个哈希值对于文本陈述,哈希值然后帮助RDBMS在共享池里面很容易的找到已经有的SQL。
例如:- 'select count(*) from emp' hashes to the value 4085390015
我们现在给SQL创建一个parent cursor和一个single child。这无所谓对于一条可能从未被共享的SQL语句来说-当第一次解析一个被创建的parent和单一的child。最简单的对这些理解的方法是PARENT cursor是代表哈希值child cursor(s)代表SQL的元数据。
什么是SQL‘元数据’?:
元数据是所有进入一条语句运行得信息。例如,我给予示例用户(scott)拥有EMP,因此,OBJECT_ID指向这些用户拥有的EMP表。当用户使用SCOTT登录时,优化程序在登录的时候被初始化,所以这也被优化,所以是元数据,在这篇文章中后面将会有其他的关于元数据的例子。
比如说这些登录退出系统并且立刻重新登录。然后再一次运行同样的命令(比如同样的用户)。这次在共享池里面已经有SQL(当是我们不知道)。我们混杂这些陈述然后再共享池里面寻找哈希值。如果我们找到,然后通过children寻找确定的如果有的话(比如:同样的元数据)。如果它是,我们就能够共享SQL语句。
现在又一个用户 ‘TEST’有EMP自己的版本。如果那些用户立刻运行上面的select语句然后将要发生:
1. 语句被弄散-值为4085390015
2. SQL将在共享池里被发现当已经存在
3. children被扫描(这时候我们有一个child)
4. 因为TEST拥有的EMP表的OBJECT_ID和scott我们有一个’mismatch’的OBJECT_ID不一样
5. 我们为此创建一个新的child-我们目前有一个PARENT 和 2 个CHILDREN。
6. 对于独享的游标,请阅读处理笔记和解析独享/更高的版本。
7. 请跟随步骤4学怎样运行verions_rpt脚本格式化在NOTE.438755.1.v$sql_shared_cursor。
2. 怎样查看版本,为什么不能独享?
运用上面的例子在共享池里检查我们可以看的SQL。
SCOTT runs select count(*) from emp
我们可以运行下面的指令来看PARENT声明和他们的哈希值与地址。
select sql_text, hash_value,address from v$sqlarea where sql_text like 'select count(*) from emp%';
SQL_TEXT HASH_VALUE ADDRESS
------------------------------------- ----------------
select count(*) from emp 4085390015 0000000386BC2E58
To see the CHILDREN (I expect to see 1 at this point) :-
9i - select * from v$sql_shared_cursor where kglhdpar = '0000000386BC2E58'
10G - select * from v$sql_shared_cursor where address = '0000000386BC2E58'
ADDRESS KGLHDPAR U S O O S L S E B P I S T A B D L T R I I R L I O S M U T N F
---------------- ---------------- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
0000000386BC2D08 0000000386BC2E58 N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N
我们可以看见我们有一个单一的single child (ADDRESS 0000000386BC2D08)。错配信息(USOOSL etc)全部是N因为这是第一个child,现在,如果我随着其他用户登录和运行同样的select (select count(*) from emp)会出现如下输出:
ADDRESS KGLHDPAR U S O O S L S E B P I S T A B D L T R I I R L I O S M U T N F
---------------- ---------------- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
0000000386BC2D08 0000000386BC2E58 N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N
0000000386A91AA0 0000000386BC2E58 N N N N N N N N N N N N N Y N N N Y N N N N N N N N N N N N N
我们现在可以看到第二个child ( 0000000386A91AA0),这就是为什么第一次不能被共享的原因,原因有(1)AUTH_CHECK_MISMATCH 和(2) TRANSLATION_MISMATCH,这是最主要的因为对象在我的新用户之下,不能映射到其他的SCOTT(当前的child)。所以,鉴定失败因为我不能访问SCOTTS对象,转换失败因为我们的object_ids不一样。
3. v$SQL_SHARED_CURSOR的意义?
下面的原因清单给予了同样的一些可以执行的例子(标有**是经常见到的):
1. UNBOUND_CURSOR-当前的child cursor没有被完全建立(换句话说,没有被充分运用)
2. SQL_TYPE_MISMATCH –SQL类型不能匹配当前的child cursor
3. **OPTIMIZER_MISMATCH –优化程序环境不能匹配当前的child cursor
select count(*) from emp; ->> 1 PARENT, 1 CHILD
alter session set optimizer_mode=ALL_ROWS
select count(*) from emp; ->> 1 PARENT, 2 CHILDREN (The optimizer mode has changed and therefore the existing child cannot be reused)
(The same applies with events - if I turned on tracing with 10046 than I would get the OPTIMIZER_MISMATCH again and a 3rd child)
OUTLINE_MISMATCH –大纲不能匹配当前的child cursor
如果我的用户对这些指令已经创建存储大纲,他们已经存储在seperate categories里面("OUTLINES1" 和 "OUTLINES2"):
alter session set use_stored_outlines = OUTLINES1;
select count(*) from emp;
alter session set use_stored_oulines= OUTLINES2;
select count(*) from emp;
è Would create a 2nd child as the outline used is different than the first run.
STATS_ROW_MISMATCH –当前的统计不能匹配当前的child cursor
检查10046/sql_trace在期间没有开始所以会导致这些
LITERAL_MISMATCH - Non-data literal值不能匹配当前的child cursor
SEC_DEPTH_MISMATCH –安全级别不能匹配当前的child cursor
EXPLAIN_PLAN_CURSOR - child cursor是一个注释光标,不应该被共享
Explain plan statements will generate a new child by default-错配将是这个
BUFFERED_DML_MISMATCH –缓存数据操纵(DML)不能匹配当前的child cursor
PDML_ENV_MISMATCH – PDML环境不能匹配当前的child cursor
INST_DRTLD_MISMATCH - Insert direct load不能匹配当前的child cursor
SLAVE_QC_MISMATCH –当前的child cursor是一个从属的,新的一个被协调器创造
TYPECHECK_MISMATCH –当前的child cursor没有被充分的利用
AUTH_CHECK_MISMATCH –对当前的child cursor权限/转化检测失败
用户没有权限访问对象在游标的一些先前的版本。典型的例子就是即每个用户都有它自己的备份表
**BIND_MISMATCH –包装的元数据不能匹配当前的child cursor
variable a varchar2(100);
select count(*) from emp where ename = :a ->> 1 PARENT, 1 CHILD
variable a varchar2(400);
select count(*) from emp where ename = :a ->> 1 PARENT, 2 CHILDREN (The bind 'a' has now changed in definition)
DESCRIBE_MISMATCH - typecheck heap不能呈现在child cursor描述期间
LANGUAGE_MISMATCH –语言处理不能匹配child cursor
TRANSLATION_MISMATCH –当前child cursor的基本对象不能匹配
对象的定义不能匹配一些当前的版本。通常这是表示同样的错误"AUTH_CHECK_MISMATCH"无论对象不相同
ROW_LEVEL_SEC_MISMATCH –安全级别不能匹配
INSUFF_PRIVS –当前child cursor引用对象的权限不足
INSUFF_PRIVS_REM –当前child cursor应用远程的对象权限不足
REMOTE_TRANS_MISMATCH –当前child cursor的 remote base对象不能匹配
USER1: select count(*) from table@remote_db
USER2: select count(*) from table@remote_db (Although the SQL is identical, the dblink pointed to by remote_db may be a private dblink which resolves
to a different object altogether)
LOGMINER_SESSION_MISMATCH
INCOMP_LTRL_MISMATCH
OVERLAP_TIME_ error_on_overlap_time错配
SQL_REDIRECT_MISMATCH –SQL重定向错配
MV_QUERY_GEN_MISMATCH - materialized view query generation
USER_BIND_PEEK_MISMATCH - user bind peek错配
TYPCHK_DEP_MISMATCH - scursor has typecheck dependencie
NO_TRIGGER_ no trigger错配
FLASHBACK_CURSOR – 没有游标共享用于闪回
ANYDATA_TRANSFORMATION – anydata转换改变
INCOMPLETE_CURSOR –不完全的游标
当绑定长度可以升级(i.e.我们找到一个child cursor可以匹配所有的,除了绑定的长度没有足够的长度)。这种情况下,我们标记旧的游标是不可用的
创建一个新的。意思是足够版本可以被忽视。
TOP_LEVEL_RPI_CURSOR - top level/rpi cursor
In a Parallel Query invocation this is expected behaviour (we purposely do not share)
DIFFERENT_LONG_LENGTH –不同的长度
LOGICAL_STANDBY_APPLY –逻辑备用申请错配
DIFF_CALL_DURN –请求时间不同
BIND_UACS_DIFF - bind uacs错配
PLSQL_CMP_SWITCHS_DIFF plsql 编译器开关错配
CURSOR_PARTS_MISMATCH - cursor-parts executed错配
STB_OBJECT_MISMATCH – STB对象不同(当前的)
ROW_SHIP_MISMATCH - row shipping capability错配
PQ_SLAVE_MISMATCH - PQ slave错配
TOP_LEVEL_DDL_MISMATCH –顶级的DDL光标
MULTI_PX_MISMATCH - multi-px and slave-compiled cursor
BIND_PEEKED_PQ_MISMATCH - bind-peeked PQ cursor
MV_REWRITE_MISMATCH - MV rewrite cursor
ROLL_INVALID_MISMATCH - rolling invalidation window exceeded
See NOTE: 557661.1 .这是由于里DBMS_STATS里面的波动的无效的容量。Child不能被共享随着无效的窗口被共享。
OPTIMIZER_MODE_MISMATCH –优化程序模块错配
PX_MISMATCH - parallel query错配
如果运行11.1.0.6 和 RAC参见BUG7352775。检查如果paralle_instance_groups设置然后instance_groups is设置一样。
MV_STALEOBJ_MISMATCH - mv stale对象错配
FLASHBACK_TABLE_MISMATCH –闪回表错配
LITREP_COMP_MISMATCH - literal replacement compilation错配
New in 11g (incomplete):
PLSQL_DEBUG – 调试错配
调试参数plsql_debug设置为true
LOAD_OPTIMIZER_STATS -负荷优化统计数据游标的共享
ACL_MISMATCH - Check ACL错配
FLASHBACK_ARCHIVE_MISMATCH -闪回存档错配
LOCK_USER_SCHEMA_FAILED -无法锁定用户和模式
REMOTE_MAPPING_MISMATCH - Remote mapping错配
LOAD_RUNTIME_HEAP_FAILED -执行时间堆错配
HASH_MATCH_FAILED -哈希错配
如果共享失败导致一个哈希错配,设置成”Y”
3. Version_rpt脚本:
version_rp脚本也可以运行生成一个v$sql_shared_cursor的概要报表参加附加的诊断信息。
运行脚本—生成游标的所有报告和超过100个版本运用SQL_ID (10g and up):
select b.* from v$sqlarea a ,table(version_rpt(a.sql_id)) b where loaded_versions >=100;
-- Generate reports for all cursors with more than 100 versions using HASH_VALUE:
select b.* from v$sqlarea a ,table(version_rpt(null,a.hash_value)) b where loaded_versions>=100;
-- Generate the report for cursor with sql_id cyzznbykb509s:
select * from table(version_rpt('cyzznbykb509s'));
4. 进一步追踪可供使用的
解决方案:
在10G里面可能用到CURSORTRACE来帮助调查为什么游标没有被共享。为了得到详细的SQL语句描绘,你首先必须获得哈希值。然后设置跟踪使用:
改变系统设置事件
'immediate trace name cursortrace level 577, address hash_value';
(level 578/580 can be used for high level tracing (577=level 1, 578=level 2, 580=level 3)
This will write a trace file to user_dump_dest each time we try to reuse the cursor.
To turn off tracing use:-
改变系统设置事件
'immediate trace name cursortrace level 2147483648, address 1';
请注意:BUG5555371存于10.2(固定的10.2.0.4)这个地方游标跟踪不能完全关掉,单线线路将仍然被追踪
5.Are there any times when a high version count is expected even though BINDS are being used?
解决方案:
Consider the following where cursor_sharing=SIMILAR
select * from emp where sal > 100;
select * from emp where sal > 101;
select * from emp where sal > 102;
select * from emp where sal > 103;
select * from emp where sal > 104;
SELECT sql_text,version_count,address
FROM V$SQLAREA
WHERE sql_text like 'select %';
SELECT * FROM V$SQL_SHARED_CURSOR WHERE kglhdpar = '&my_addr';
你将会看到一些版本,每一个都不明显因为没有被共享
说明:
SIMILAR 和 FORCE的不同是SIMILAR分离类似的声明和共享SQL区域,没有退化执行计划。设置CURSOR_SHARING为FORCE分离类似的声明共享SQL区域,可能退化执行计划。
也可能出现10046追踪的报告(level 4/12 - BINDS)如果一个绑定被认为是存在不安全的
The flag oacfl2 in 9i and fl2 in 10g will show if a variable is unsafe.
BINDS #2:
bind 0: dty=2 mxl=22(04) mal=00 scl=00 pre=00 oacflg=10 oacfl2=500 size=24
offset=0
bfp=1036d6408 bln=22 avl=04 flg=09
value=16064
bind 1: dty=2 mxl=22(04) mal=00 scl=00 pre=00 oacflg=10 oacfl2=500 size=24
offset=0
bfp=1036d4340 bln=22 avl=04 flg=09