转载

sql version count引发cursor:pin s wait x及library cache latch library cache lock

背景

   某Q友在其生产系统AWR发现library cache latch及library cache lock及cursor:pin s wait x等待事件非常严重,经排查发生某些底层SQL的多版本现象非常严重,最高达到4000多左右
结论
   1,oracle为了控制某个SQL的子游标个数不止过高过多,采用绑定变量分级机制,即绑定变量的长度(字节)在一个范围内,就隶属一个子游标,否则就会新创建一个子游标
   2,可以通过v$sql_bind_metadata获取上述绑定变量分量的具体分界点
   3,v$sql_shared_cursor可以分析某SQL产生多个子游标的原因,然后进行不同的原因进行分析
   4,进一步基于第3步分析(这里子游标不能共享的原因是bind_mismatch),在MOS查找相关文档 ,发现
      High Version Count Due To BIND_MISMATCH [ID 336268.1]
   5,基于第4步,我们已经知道多版本的产生原因,现在要解决这个问题,因为是生产系统, 可以采用10503事件进行暂时控制
      但不能成功


   6,基于第5步,就要分析为何事件配置不成功,继续查看MOS,以关键字进行查找,event 10503
      发现文章:
         Bug 10274265 - Event 10503 does not work at session level [ID 10274265.8]


    7,基于第6步,要思考下,即便配置10503事件成功了,毕竟是生产系统,会不会引发其它的一些问题或BUG呢,还是老办法,查看MOS
         
event可能导致ORA-600: [kxspoac : EXL 1]错误


ORA-600: [kxspoac : EXL 1] Occuring During Query If Event 10503 Is Set [ID 810194.1]






    8,由上述引发一些思考:






--由此可见ORACLE知识联系是非常复杂的,要调整一个参数,必须要从全方位考虑与分析


1,配置参数的命令是什么
2,如果配置参数不成功,它为何不成功,可能也有相关的MOS文章进行介绍
3,如果配置参数成功,会引发什么其它的问题,也要进行全面考虑,否则解决旧问题,引发新问题


引申一下,可见应用人员设计表以及开发人员,在编写代码时,也要考虑到这点,比如:不要在声明变量长度时
过分声明,比如本来20字节就够了,你声明了1000个字节,而且每个开发人员声明长度不同
,这样就会引发本文的子游标不能共共享的问题




4,基于关镇字查看是否是相关的BUG


5,进一步引证了TOP 5等待事件有时未必是因,很可能它只是一个果,而且它的原因不在本时间点采样的AWR(或者说不能很明白得看出来)
   也就是说需要你查看此时间点之前的AWR进行分析




分析


SQL> select sql_id,sql_text from v$sql where lower(sql_text) like '%select pos#,intcol#%';


SQL_ID        SQL_TEXT
------------- ----------------------------------------------------------------------------------------------------
1qb4fr2qc8jsu select sql_id,sql_text from v$sql where lower(sql_text) like '%select pos#,intcol#%'
6769wyy3yf66f select pos#,intcol#,col#,spare1,bo#,spare2 from icol$ where obj#=:1


SQL> select sql_id,count(*) from v$sql where sql_id='6769wyy3yf66f' group by sql_id;


SQL_ID          COUNT(*)
------------- ----------
6769wyy3yf66f          1


SQL> select sid,event,prev_sql_id,sql_id from v$session where nvl(prev_sql_id,sql_id)='6769wyy3yf66f';


no rows selected


SQL> select count(*) from v$session where nvl(prev_sql_id,sql_id)='6769wyy3yf66f';


  COUNT(*)
----------
         0


SQL> desc icol$;
 Name              Null?    Type
 ----------------- -------- ------------
 OBJ#              NOT NULL NUMBER
 BO#               NOT NULL NUMBER
 COL#              NOT NULL NUMBER
 POS#              NOT NULL NUMBER
 SEGCOL#           NOT NULL NUMBER
 SEGCOLLENGTH      NOT NULL NUMBER
 OFFSET            NOT NULL NUMBER
 INTCOL#           NOT NULL NUMBER
 SPARE1                     NUMBER
 SPARE2                     NUMBER
 SPARE3                     NUMBER
 SPARE4                     VARCHAR2(100
                            0)
 SPARE5                     VARCHAR2(100
                            0)
 SPARE6                     DATE


SQL> select count(*) from icol$;


  COUNT(*)
----------
      2416




SQL> select obj#,bo#,col#,pos#,segcol#,offset,spare1,spare2 from icol$ where rownum<=10 order by 1;


      OBJ#        BO#       COL#       POS#    SEGCOL#     OFFSET     SPARE1     SPARE2
---------- ---------- ---------- ---------- ---------- ---------- ---------- ----------
         3          2          1          1          0          0          0          0
         7          6          1          1          0          0          0          0
         9          8          1          1          0          0          0          0
         9          8          2          2          0          0          0          0
         9          8          3          3          0          0          0          0
        11         10          1          1          0          0          0          0
        24         23          1          1          0          0          0          0
        24         23          2          2          0          0          0          0
        26         25          1          1          0          0          0          0
        26         25          2          2          0          0          0          0


10 rows selected.


create table icol$                                     /* index column table */
( obj#          number not null,                      /* index object number */
  bo#           number not null,                       /* base object number */
  col#          number not null,                            /* column number */
  pos#          number not null,        /* column position number as created */
  segcol#       number not null,                 /* column number in segment */
  segcollength  number not null,             /* length of the segment column */
  offset        number not null,                         /* offset of column */
  intcol#       number not null,                   /* internal column number */
  spare1        number,                                              /* flag */
                                              /* 0x01: this is an expression */
                                                  /* 0x02: desc index column */
                                          /* 0x04: filter by col for dom idx */
                                           /* 0x08: order by col for dom idx */
  spare2        number,            /* dimension table internal column number */
  spare3        number,           /* pos# of col in order by list of dom idx */
  spare4        varchar2(1000),
  spare5        varchar2(1000),
  spare6        date
)
cluster c_obj#(bo#)




SQL> create table t_bind(a varchar2(100));


Table created.


SQL> insert into t_bind values(1);


1 row created.


SQL> commit;


Commit complete.


SQL> var x varchar2(10);
SQL> select a from t_bind where a=:x;


no rows selected


SQL> var x varchar2(100);
SQL> select a from t_bind where a=:x;


no rows selected


SQL> select sql_id,sql_text from v$sql where sql_text like '%select a from t_bind where a=%';


SQL_ID        SQL_TEXT
------------- ----------------------------------------------------------------------------------------------------
3swjj5kc9kfkp select a from t_bind where a=:x
3swjj5kc9kfkp select a from t_bind where a=:x


SQL> select sql_id,address,child_address,child_number,bind_mismatch from v$sql_shared_cursor where sql_id='3swjj5kc9kfkp';


SQL_ID        ADDRESS          CHILD_ADDRESS    CHILD_NUMBER B
------------- ---------------- ---------------- ------------ -
3swjj5kc9kfkp 0000000064964090 0000000064961FC0            0 N
3swjj5kc9kfkp 0000000064964090 00000000649A1FA8            1 Y


SQL> var x varchar2(38);
SQL> select a from t_bind where a=:x;


no rows selected


---发现子游标没有继续增加
SQL> select sql_id,address,child_address,child_number,bind_mismatch from v$sql_shared_cursor where sql_id='3swjj5kc9kfkp';


SQL_ID        ADDRESS          CHILD_ADDRESS    CHILD_NUMBER B
------------- ---------------- ---------------- ------------ -
3swjj5kc9kfkp 0000000064964090 0000000064961FC0            0 N
3swjj5kc9kfkp 0000000064964090 00000000649A1FA8            1 Y    




SQL> var x varchar2(50);
SQL> select a from t_bind where a=:x;


no rows selected


SQL> select sql_id,address,child_address,child_number,bind_mismatch from v$sql_shared_cursor where sql_id='3swjj5kc9kfkp';


SQL_ID        ADDRESS          CHILD_ADDRESS    CHILD_NUMBER B
------------- ---------------- ---------------- ------------ -
3swjj5kc9kfkp 0000000064964090 0000000064961FC0            0 N
3swjj5kc9kfkp 0000000064964090 00000000649A1FA8            1 Y


---会不会变量长度,也有个分级,不同分级的长度,会产生新的子游标呢
SQL> alter table t_bind modify a varchar2(1000);


Table altered.


SQL> select sql_id,address,child_address,child_number,bind_mismatch from v$sql_shared_cursor where sql_id='3swjj5kc9kfkp';


no rows selected


SQL> var x varchar2(10);
SQL> select a from t_bind where a=:x;


no rows selected


SQL> select sql_id,address,child_address,child_number,bind_mismatch from v$sql_shared_cursor where sql_id='3swjj5kc9kfkp';


SQL_ID        ADDRESS          CHILD_ADDRESS    CHILD_NUMBER B
------------- ---------------- ---------------- ------------ -
3swjj5kc9kfkp 0000000064964090 0000000064961FC0            0 N


SQL> var x varchar2(100);
SQL> select a from t_bind where a=:x;


no rows selected


SQL> select sql_id,address,child_address,child_number,bind_mismatch from v$sql_shared_cursor where sql_id='3swjj5kc9kfkp';


SQL_ID        ADDRESS          CHILD_ADDRESS    CHILD_NUMBER B
------------- ---------------- ---------------- ------------ -
3swjj5kc9kfkp 0000000064964090 0000000064961FC0            0 N
3swjj5kc9kfkp 0000000064964090 00000000649A1FA8            1 Y


SQL> var x varchar2(200);
SQL> select a from t_bind where a=:x;


no rows selected


SQL> select sql_id,address,child_address,child_number,bind_mismatch from v$sql_shared_cursor where sql_id='3swjj5kc9kfkp';


SQL_ID        ADDRESS          CHILD_ADDRESS    CHILD_NUMBER B
------------- ---------------- ---------------- ------------ -
3swjj5kc9kfkp 0000000064964090 0000000064961FC0            0 N
3swjj5kc9kfkp 0000000064964090 00000000649A1FA8            1 N




SQL> var x varchar2(500);
SQL> select a from t_bind where a=:x;


no rows selected


SQL> select sql_id,address,child_address,child_number,bind_mismatch from v$sql_shared_cursor where sql_id='3swjj5kc9kfkp';


SQL_ID        ADDRESS          CHILD_ADDRESS    CHILD_NUMBER B
------------- ---------------- ---------------- ------------ -
3swjj5kc9kfkp 0000000064964090 0000000064961FC0            0 N
3swjj5kc9kfkp 0000000064964090 00000000649A1FA8            1 N


SQL> var x varchar2(1000);
SQL> select a from t_bind where a=:x;


no rows selected


SQL> select sql_id,address,child_address,child_number,bind_mismatch from v$sql_shared_cursor where sql_id='3swjj5kc9kfkp';


SQL_ID        ADDRESS          CHILD_ADDRESS    CHILD_NUMBER B
------------- ---------------- ---------------- ------------ -
3swjj5kc9kfkp 0000000064964090 0000000064961FC0            0 N
3swjj5kc9kfkp 0000000064964090 00000000649A1FA8            1 N


---可见刷新共享池只会保存
SQL> alter system flush shared_pool;


System altered.


SQL> select sql_id,address,child_address,child_number,bind_mismatch from v$sql_shared_cursor where sql_id='3swjj5kc9kfkp';


SQL_ID        ADDRESS          CHILD_ADDRESS    CHILD_NUMBER B
------------- ---------------- ---------------- ------------ -
3swjj5kc9kfkp 0000000064964090 00000000649A1FA8            1 N






---继续分析下到底绑定变量分级,到度在哪些值范围内,隶属一个子游标,否则会新生一个子游标


经查MOS,发现文章:High Version Count Due To BIND_MISMATCH [ID 336268.1]
对于绑定变量,ORACLE根据变量长度进行了分级,对于VARCHAR2类型共有如下4级:


第一级:1-32
第二级:33-128
第三级:129-2000
第四级:2000+


SQL> alter table t_bind modify a varchar2(300);


Table altered.




SQL> var x varchar2(50);
SQL> select a from t_bind where a=:x;


no rows selected


SQL> select sql_id,address,child_address,child_number,bind_mismatch from v$sql_shared_cursor where sql_id='3swjj5kc9kfkp';


SQL_ID        ADDRESS          CHILD_ADDRESS    CHILD_NUMBER B
------------- ---------------- ---------------- ------------ -
3swjj5kc9kfkp 0000000064964090 0000000064961FC0            0 N


SQL> var x varchar2(129);
SQL> select a from t_bind where a=:x;


no rows selected


SQL> select sql_id,address,child_address,child_number,bind_mismatch from v$sql_shared_cursor where sql_id='3swjj5kc9kfkp';


SQL_ID        ADDRESS          CHILD_ADDRESS    CHILD_NUMBER B
------------- ---------------- ---------------- ------------ -
3swjj5kc9kfkp 0000000064964090 0000000064961FC0            0 N
3swjj5kc9kfkp 0000000064964090 00000000649A1FA8            1 Y




SQL> var x varchar2(2001);
SQL> select a from t_bind where a=:x;


no rows selected


SQL> select sql_id,address,child_address,child_number,bind_mismatch from v$sql_shared_cursor where sql_id='3swjj5kc9kfkp';


SQL_ID        ADDRESS          CHILD_ADDRESS    CHILD_NUMBER B
------------- ---------------- ---------------- ------------ -
3swjj5kc9kfkp 0000000064964090 0000000064961FC0            0 N
3swjj5kc9kfkp 0000000064964090 00000000649A1FA8            1 Y
3swjj5kc9kfkp 0000000064964090 0000000066EA5F40            2 Y




SQL> var x varchar2(15);
SQL> select a from t_bind where a=:x;


no rows selected




---mos说,可以用10503事件暂时解决上述版本过高问题,好像10503事件没起作用
SQL> alter session set events '10503  trace name context forever ,level 4096';


Session altered.


SQL> alter table t_bind modify a varchar2(300);


Table altered.


SQL> var x varchar2(15);
SQL> select a from t_bind where a=:x;


no rows selected


SQL> select sql_id,address,child_address,child_number,bind_mismatch from v$sql_shared_cursor where sql_id='3swjj5kc9kfkp';


SQL_ID        ADDRESS          CHILD_ADDRESS    CHILD_NUMBER B
------------- ---------------- ---------------- ------------ -
3swjj5kc9kfkp 0000000064964090 0000000064961FC0            0 N




SQL> var x varchar2(120);
SQL> select a from t_bind where a=:x;


no rows selected


SQL> select sql_id,address,child_address,child_number,bind_mismatch from v$sql_shared_cursor where sql_id='3swjj5kc9kfkp';


SQL_ID        ADDRESS          CHILD_ADDRESS    CHILD_NUMBER B
------------- ---------------- ---------------- ------------ -
3swjj5kc9kfkp 0000000064964090 0000000064961FC0            0 N
3swjj5kc9kfkp 0000000064964090 00000000649A1FA8            1 Y


SQL> var x varchar2(600);
SQL> select a from t_bind where a=:x;


no rows selected


SQL> select sql_id,address,child_address,child_number,bind_mismatch from v$sql_shared_cursor where sql_id='3swjj5kc9kfkp';


SQL_ID        ADDRESS          CHILD_ADDRESS    CHILD_NUMBER B
------------- ---------------- ---------------- ------------ -
3swjj5kc9kfkp 0000000064964090 0000000064961FC0            0 N
3swjj5kc9kfkp 0000000064964090 00000000649A1FA8            1 Y


SQL> var x varchar2(2600);
SQL> select a from t_bind where a=:x;


no rows selected


SQL> select sql_id,address,child_address,child_number,bind_mismatch from v$sql_shared_cursor where sql_id='3swjj5kc9kfkp';


SQL_ID        ADDRESS          CHILD_ADDRESS    CHILD_NUMBER B
------------- ---------------- ---------------- ------------ -
3swjj5kc9kfkp 0000000064964090 0000000064961FC0            0 N
3swjj5kc9kfkp 0000000064964090 00000000649A1FA8            1 Y
3swjj5kc9kfkp 0000000064964090 0000000066EA5F40            2 Y




----继续分析10503事件为何不生效,看来不是105032命令的次序问题


SQL> alter session set events '10503  trace name context level 4096,forever';


Session altered.


SQL> alter table t_bind modify a varchar2(300);


Table altered.




SQL> var x varchar2(12);
SQL> select a from t_bind where a=:x;


no rows selected


SQL> select sql_id,address,child_address,child_number,bind_mismatch from v$sql_shared_cursor where sql_id='3swjj5kc9kfkp';


SQL_ID        ADDRESS          CHILD_ADDRESS    CHILD_NUMBER B
------------- ---------------- ---------------- ------------ -
3swjj5kc9kfkp 0000000064964090 0000000064961FC0            0 N




SQL> var x varchar2(100);
SQL> select a from t_bind where a=:x;


no rows selected


SQL> select sql_id,address,child_address,child_number,bind_mismatch from v$sql_shared_cursor where sql_id='3swjj5kc9kfkp';


SQL_ID        ADDRESS          CHILD_ADDRESS    CHILD_NUMBER B
------------- ---------------- ---------------- ------------ -
3swjj5kc9kfkp 0000000064964090 0000000064961FC0            0 N
3swjj5kc9kfkp 0000000064964090 00000000649A1FA8            1 Y


SQL> var x varchar2(250);
SQL> select a from t_bind where a=:x;


no rows selected


SQL> select sql_id,address,child_address,child_number,bind_mismatch from v$sql_shared_cursor where sql_id='3swjj5kc9kfkp';


SQL_ID        ADDRESS          CHILD_ADDRESS    CHILD_NUMBER B
------------- ---------------- ---------------- ------------ -
3swjj5kc9kfkp 0000000064964090 0000000064961FC0            0 N
3swjj5kc9kfkp 0000000064964090 00000000649A1FA8            1 Y


SQL> var x varchar2(2500);
SQL> select a from t_bind where a=:x;


no rows selected


SQL> select sql_id,address,child_address,child_number,bind_mismatch from v$sql_shared_cursor where sql_id='3swjj5kc9kfkp';


SQL_ID        ADDRESS          CHILD_ADDRESS    CHILD_NUMBER B
------------- ---------------- ---------------- ------------ -
3swjj5kc9kfkp 0000000064964090 0000000064961FC0            0 N
3swjj5kc9kfkp 0000000064964090 00000000649A1FA8            1 Y
3swjj5kc9kfkp 0000000064964090 0000000066EA5F40            2 Y


---继续经查MOS,发现文章
Bug 10274265 - Event 10503 does not work at session level [ID 10274265.8]


可见即使在会话层面配置了10503事件,仍然不会生效


---而且即使设置10503事件成功,可能会引发ORA-600报错
event可能导致ORA-600: [kxspoac : EXL 1]错误


ORA-600: [kxspoac : EXL 1] Occuring During Query If Event 10503 Is Set [ID 810194.1]




--由此可见ORACLE知识联系是非常复杂的,要调整一个参数,必须要从全方位考虑与分析


1,配置参数的命令是什么
2,如果配置参数不成功,它为何不成功,可能也有相关的MOS文章进行介绍
3,如果配置参数成功,会引发什么其它的问题,也要进行全面考虑,否则解决旧问题,引发新问题


引申一下,可见应用人员设计表以及开发人员,在编写代码时,也要考虑到这点,比如:不要在声明变量长度时
过分声明,比如本来20字节就够了,你声明了1000个字节,而且每个开发人员声明长度不同
,这样就会引发本文的子游标不能共共享的问题




基于关镇字查看是否是相关的BUG










正文到此结束
Loading...