Loading

解析错误导致library cache lock+library cache: mutex X

1.查看当前数据库等待事件

##数据库等待事件发现大量的library cache lock
##从下图中的等待事件查询,基本上可以判定是一条SQL语句导致的,大量回话被1996回话阻塞,1996被回话1354回话阻塞,1354对应的blockding session为空。且所有的回话执行的都是同一条SQL
 
 

2.获取SQL_TEXT

##通过sql_id无法获取到sql_text
##分析到这里根据经验大概是因为错误的SQL文本解析导致的
23:14:57 SQL> select sql_text from v$sql where sql_id='avsaksqw45m7g';
no rows selected
 
##mos提供如下方式进行查询错误的SQL文本导致的解析问题sql_id

 

 

3.抓取awr报告获取如下信息,并分析

##抓取awr报告,从awr报告里面进一步确定问题

 

 

 

##时间统计模型
##从这里可以看到系统主要时间消耗是解析失败
 
##分析到这里基本上可以确定是因为解析失败导致的问题故障,这里我们需要进一步确定问题SQL,因为数据库正常情况下无法抓取解析失败的SQL,我们需要设置event事件来辅助解决此类问题。
 
##查看有关解析SQL
##这里的第一位sql_id和我们从数据查找到的等待事件显然不是一个问题,对应sql_id的sql_text无法找到
##说明:这里的一个调度进程insert,是查看数据库性能信息的监控程序,这里解析1239次,一次也没有执行成功显然是不正常的,对于版本过多的SQL,一次软解析甚至不如重新执行一次硬解析来的高效,这里因为数据库版本是11.2.0.4,因此可以通过修改隐含参数"_CURSOR_OBSOLETE_THRESHOLD",当SQL版本超过这个参数设定后,直接重新硬解析。这里是问题之外的其他问题,这里先不做深究。

 

 4.开启trace事件进行解析失败SQL追踪

ALTER SYSTEM SET EVENTS '10035 trace name context forever, level 1';
##设置event事件后,数据库alter日志开始出现大量硬解析问题SQL,但是单单从SQL语句中感觉不到什么太大问题

##检查对应的SQL语句可以正常执行

23:18:10 SQL> select Max(CHECKTIME) from key.M_GLOBALPROCESSINFO;
MAX(CHECKTIME)
------------------------------
2022-05-07 09:26:16
 

5.为什么可以正常执行呢????

##检查错误代码输出--无效的字符??但是从日志中看解析失败的语句是正常的啊???为啥呢????
[oracle@oracle11g ~]$ oerr ora 911
00911, 00000, "invalid character"
// *Cause: identifiers may not start with any ASCII character other than
//         letters and numbers.  $#_ are also allowed after the first
//         character.  Identifiers enclosed by doublequotes may contain
//         any character other than a doublequote.  Alternative quotes
//         (q'#...#') cannot use spaces, tabs, or carriage returns as
//         delimiters.  For all other contexts, consult the SQL Language
//         Reference Manual.
// *Action:
 
 
##测试1执行错误的文本
SQL> select * from afadsfa;
select * from afadsfa
              *
ERROR at line 1:
ORA-00942: table or view does not exist
 
##ALTER日志对应的信息
##从这里我们发现,SQL语句在数据库中解析后,并没有最后的分号?是不是这个问题导致的呢?我们接着测试
PARSE ERROR: ospid=20936, error=942 for statement:
select * from tabasfa
 
 
##测试2执行错误的文本多出一个分号
 
SQL> select count(*) from t1;;
select count(*) from t1;
                       *
ERROR at line 1:
ORA-00911: invalid character
 
##alert日志对应的信息
##这里alert日志中输出的信息,发现解析文本后面确确实实多了一个分号,和我们上述的情况是一致的。
PARSE ERROR: ospid=24879, error=911 for statement:
select count(*) from t1;
 
问题分析到这里,基本上可以判断确确实实是SQL语法有问题,但是开发不可能蠢到一个语句的结束出现两个分号,因此判断是plsql代码中存在问题,进行了如下测试

 

 6.问题处理解决

 ##大量无效语句会导致CPU和library cache征用,最好的处理办法就是解决应用错误的SQL语句,但是作为临时解决方法,可以通过调整隐含参数减轻不正确解析的影响
##_cursor_features_enabled隐含参数默认是2,我们需要在这个基础上加32,需要重新启动数据库
SQL> alter system set "_cursor_features_enabled" = 34 scope=spfile;
System altered.
 
##设置参数并重启后,解析错误的记录在表sqlerror$中,后续的错误的SQL解析成本会降低,不会产生SQL硬解析所有的成本,而是一小部分成本,这样就减少了资源消耗
##每条错误的SQL只会记录一条记录

 

 

参考MOS:1353015.1
 
 
 
 
 
 
 
 
posted @ 2022-05-10 10:22  李行行  阅读(651)  评论(0编辑  收藏  举报