本文由我和公司同事问心共同测试分析完成。

很多时候我们会有这样一个误区,语法错误或者对象不存在应该在语法语义检查这个步骤就结束了,怎么还会存在共享池里面呢?带着这个几个问题我们做几个简单的测试。

我们先了解下什么是解析失败的 SQL?
1、SQL语法错误
2、访问的对象不存在
3、没有权限

那么怎么证明有哪些解析失败的SQL
我们知道 SQL 语句必须至少是一个父游标一个子游标存在的,当然生产中很多情况下都是一父多子的情况。
父游标与子游标结构是一样的,区别在于sql解析相关信息存储在父游标对应的heap 0中,而sql的执行计划等信息存储在子
游标对应的库缓存对象heap 6内存空间中。另外父游标的 heap 0中存储着子游标的句柄地址。如果解析错误的SQL在共
享池中存储的话那么必然要产生一个父游标然后父游标里面存储的有相关的解析信息,但是子游标的?既然解析失败那么就
没有产生执行计划。
则利用这一点可以找到解析失败的语句。
父游标句柄对地址可以在 x$kglob 视图中查询到,KGLHDPAR=KGLHDADR 的记录为父游标,
而KGLHDPAR<>KGLHDADR为子游标

X$KGLOB

该视图定义为 [K]ernel[G]eneric [L]ibrary Cache Manager
KGLHDADR RAW(4|8) Address of kglhd for this object
可以看到:
KGLOBHD0 RAW(4|8) Address of heap 0 descriptor
KGLOBHD6 RAW(4|8) Address of heap 6 descriptor

SQL> select * from scott.emp;
SQL> col kglnaobj for a50;
SQL> select kglnaobj,kglnatim,kglhdpar,kglhdadr,KGLOBHD0,KGLOBHD6 from x$kglob where KGLNAOBJ='select * from scott.emp';

KGLNAOBJ                                           KGLNATIM            KGLHDPAR         KGLHDADR         KGLOBHD0         KGLOBHD6
-------------------------------------------------- ------------------- ---------------- ---------------- ---------------- ----------------
select * from scott.emp                            2017-07-07 14:54:52 0000000096AE88B0 00000000958B9A40 0000000096AE85D8 000000007713C758
select * from scott.emp                            2017-07-07 14:54:52 0000000096AE88B0 0000000096AE88B0 0000000095871858 00

x$kglcursor_child_sqlid (只包含子游标信息)
SQL> select kglnaobj,kglnatim,kglhdpar,kglhdadr,KGLOBHD0,KGLOBHD6 from x$kglcursor_child_sqlid where KGLNAOBJ='select * from scott.emp';

KGLNAOBJ                                           KGLNATIM            KGLHDPAR         KGLHDADR         KGLOBHD0         KGLOBHD6
-------------------------------------------------- ------------------- ---------------- ---------------- ---------------- ----------------
select * from scott.emp                            2017-07-07 14:54:52 0000000096AE88B0 00000000958B9A40 0000000096AE85D8 000000007713C758

0000000096AE88B0 为select * from scott.emp; 父游标句柄地址,00000000958B9A40为子游标句柄地址
子游标heap 6(KGLOBHD6)的地址为000000007713C758,句柄中存储的也就是执行计划相关的信息。
通过以上测试我们很容易找到sql的父游标的句柄还有子游标的句柄在内存中的地址。

下面做另外一个简单的测试解析错误的SQL是否有父游标和子游标生成。
SQL> select * from test;
select * from test
              *
ERROR at line 1:
ORA-00942: table or view does not exist
SQL> select kglnaobj,kglnatim,kglhdpar,kglhdadr,KGLOBHD0,KGLOBHD6 from x$kglob where KGLNAOBJ='select * from test';

KGLNAOBJ                                           KGLNATIM            KGLHDPAR         KGLHDADR         KGLOBHD0         KGLOBHD6
-------------------------------------------------- ------------------- ---------------- ---------------- ----------------                    ----------------
select * from test                                 2017-07-07 15:06:28 0000000097DDC190 0000000097F941F8 00               00
select * from test                                 2017-07-07 15:06:28 0000000097DDC190 0000000097DDC190 000000009E035698 00
SQL> select kglnaobj,kglnatim,kglhdpar,kglhdadr,KGLOBHD0,KGLOBHD6 from x$kglcursor_child_sqlid where KGLNAOBJ='select * from test';

no rows selected
可以看到没有子游标生成,因为该SQL执行错误不会有执行计划相关信息。
从x$kglob 也可以查到 kglobhd0、kglobhd6 都为空(NULL)。
在 x$kglcursor_child 视图也查不到任何信息的,v$sql v$sqlare 类似的视图也就查不到解析错误的 SQL 了。

关于解析失败的SQL还是需要获取latch,其实从上面的测试已经证明了还是要获取 shared pool 的 latch的,因为生成了父游标。
通过以上测试说明解析失败的sql只生成了父游标,而没有生成子游标和执行计划信息。

也可以用一下sql查出当前数据库中所有解析失败的sql
select kglnaobj,kglnatim,kglhdpar,kglhdadr,KGLOBHD0,KGLOBHD6 from x$kglob where kglhdpar<>kglhdadr
and  KGLOBHD6='00' and KGLOBHD0='00' order by kglnatim desc;

从整个过程来看即使解析失败父游标是需要分配空间的,如果没有使用绑定变量的情况下需要大量的分配
内存空间来保存这些解析失败语句的父游标,它不仅会持有latch:libary cache而且会持有latch:shared
pool.

最后猜测一下:

KGLNAOBJ                                           KGLNATIM            KGLHDPAR         KGLHDADR         KGLOBHD0         KGLOBHD6
-------------------------------------------------- ------------------- ---------------- ---------------- ---------------- ----------------
select * from scott.emp                            2017-07-07 14:54:52 0000000096AE88B0 00000000958B9A40 0000000096AE85D8 000000007713C758

SQL> select ksmchptr,ksmchcom,ksmchcls,ksmchsiz from x$ksmsp where KSMCHPAR='0000000096AE85D8';

KSMCHPTR         KSMCHCOM                                         KSMCHCLS                   KSMCHSIZ
---------------- ------------------------------------------------ ------------------------ ----------
000000007713AFD8 KGLH0^31fa0cc                                    recr                           4096(chunk 大小)

如上:
KGLHDADR:应该为整个游标结构体(句柄)的虚拟内存地址其地址为00000000958B9A40
KGLHDPAR:为父游标构体(句柄的)的虚拟内存地址其地址为0000000096AE88B0
而父游标的KGLHDPAR和KGLHDADR相等,子游标KGLHDPAR为父游标构体(句柄的)的虚拟内存地址,KGLHDADR为自己的
游标构体(句柄的)的虚拟内存地址
在这个结构体中有一根指针指向void* p 指向heap 0 ds描述符的内存空间,虚拟内存地址为0000000096AE85D8

ds描述符:应该也是一个结构体其中又有一根指针void* p 指向heap 0实际的虚拟内存地址为000000007713AFD8
那么heap0实际的地址为000000007713AFD8
比如:
struct ds
{
  KSMCHCOM;
  KSMCHCLS;
  KSMCHSIZ;
  .........
void* p;
}

怎么找出解析失败的sql的更多相关文章

  1. SQLServer找出执行慢的SQL语句

      SELECT (total_elapsed_time / execution_count)/1000 N'平均时间ms' ,total_elapsed_time/1000 N'总花费时间ms' , ...

  2. MySQL Innodb如何找出阻塞事务源头SQL

    在MySQL数据库中出现了阻塞问题,如何快速查找定位问题根源?在实验开始前,我们先梳理一下有什么工具或命令查看MySQL的阻塞,另外,我们也要一一对比其优劣,因为有些命令可能在实际环境下可能并不适用. ...

  3. Oracle DB 12.2(12cR2)的一个新特性:硬解析失败的SQL语句(需要符合一定条件)打印到alert_sid.log中.

    How to Identify Hard Parse Failures (Doc ID 1353015.1)Bug 16945190 - Diagnostic enhancement to dump ...

  4. 在百万数据中找出重复的数据sql

    select * from (select count(name) as isone, name from tbl_org_departments group by name) t where t.i ...

  5. (转载)处理SQL解析失败导致share pool 的争用

    通过关联x$kglcursorx$kglcursor_child_sqlid视图: 通过使用Oracle10035Event事件可以找到解析失败的SQL: 通过oraclesystemdump也可以找 ...

  6. 在一个SQL Server表中的多个列找出最大值

    在一个SQL Server表中一行的多个列找出最大值 有时候我们需要从多个相同的列里(这些列的数据类型相同)找出最大的那个值,并显示 这里给出一个例子 IF (OBJECT_ID('tempdb..# ...

  7. 如何找出你性能最差的SQL Server查询

    我经常会被反复问到这样的问题:”我有一个性能很差的SQL Server.我如何找出最差性能的查询?“.因此在今天的文章里会给你一些让你很容易找到问题答案的信息向导. 问SQL Server! SQL ...

  8. [SQL]透過redgate SQL Monitor 來找出 ASYNC_NETWORK_IO 問題

    原文:[SQL]透過redgate SQL Monitor 來找出 ASYNC_NETWORK_IO 問題 最近因為在查一個SQL的效能問題,透過 sys.dm_os_wait_stats 來取得To ...

  9. 找出sql脚本中需要创建的表空间名称和数据库用户名

    测试的工作中,经常会遇到项目交接或者搭建一个新的测试环境,而创建oracle数据库用户及表空间时,需要提前找出脚本中的 数据库用户名和表空间名,所以自己写了一个python脚本,自动找出sql脚本中的 ...

随机推荐

  1. Effective Java学习笔记--创建和销毁对象

    创建和销毁对象 一.静态工厂方法代替构造器 静态工厂方法的优缺点 优点: 1.可以自定义名称(可以将功能表述的更加清晰) 2.不必每次调用都创建新的对象(同一对象重复使用) 3.返回的类型可以是原返回 ...

  2. 数据库设计(五)第一范式(1NF)?

    In our last tutorial we learned and understood how data redundancy or repetition can lead to several ...

  3. 关于MongoDB最大连接数的查看与修改

    一. MongoDB连接数 在Linux平台下,无论是64位或者32位的MongoDB默认最大连接数都是819,WIN平台不知道,估计也没有人在 WIN平台下使用MongoDB做生产环境 [root@ ...

  4. 流媒体服务器开发笔记(2)--RTCP协议介绍

    http://blog.sina.com.cn/s/blog_53061af00100o2no.html ——————————————————————————————————————————————— ...

  5. 马尔科夫毯(Markov Blanket)

    最优特征子集:选出特征的子集,能够比较准确的代表原来的特征.马尔科夫毯(MB)是贝叶斯网络(BN)的最有特征子集. 推测贝叶斯网络的网络结构是NP问题.贝叶斯网络中一个节点T的马尔科夫毯是其父节点,子 ...

  6. 简单说明什么是递归?什么情况会使用?并使用java实现一个简单的递归程序。

    解答: 1)递归做为一种算法在程序设计语言中广泛应用.是指函数/过程/子程序在运行过程中直接或间接调用自身而产生的重入现象. 2)递归算法一般用于解决三类问题: a.数据的定义是按递归定义的.(Fib ...

  7. js indexof用法indexOf()定义和用法

    indexOf()定义和用法 indexOf() 方法可返回某个指定的字符串值在字符串中首次出现的位置. 语法 stringObject.indexOf(searchvalue,fromindex) ...

  8. ChemDraw进行自动调整的步骤

    说到化学绘图软件那就不得不提ChemDraw,起非常的经典在国内外都得到了普遍应用,最新版是ChemDraw 15.1 Pro.在使用ChemDraw化学绘图工具绘制化学图形的时候,需要循序渐进一步一 ...

  9. 关于mariadb远程连接授权的设置

    1.首先配置允许访问的用户,采用授权的方式给用户权限 1 GRANT ALL PRIVILEGES ON *.* TO 'root'@'%'IDENTIFIED BY '123456' WITH GR ...

  10. iOS-如何在项目中使用CocoaPods

    1.打开终端. 2.将项目文件夹拖入到cd空格 后面. 3.回车,看下现在的路径是. 4.我们输入vim podfile回车,建立Podfile文件. 5.进到这个界面,我们再按i编辑--你会看到下面 ...