[20191122]oracel SQL parsing function qcplgte.txt
[20191122]oracel SQL parsing function qcplgte.txt
--//昨天看了链接:https://nenadnoveljic.com/blog/memory-leak-parsing/ =>Memory Leak During Parsing
qcplgte
qcplgte is one of the auxiliary functions in Oracle database that underpin SQL parsing. In particular, this function
divides the SQL text into several parts. In Oracle 12.2, the function receives a pointer through the second argument.
The address to the next part of the SQL string to parse is stored at the 8 bytes offset. After parsing the portion of
the SQL text, the function will update the same memory location with the pointer to the substring for the next parsing
stage.
Qcplgte是Oracle数据库中支持SQL解析的辅助功能之一。尤其是这一职能将SQL文本分为几个部分。在Oracle12.2中,函数通过第二个参
数接收指针。要解析的SQL字符串的下一部分的地址存储在8字节偏移量处。在解析了在SQL文本中,函数将用指向子字符串的指针更新相
同的内存位置,以便进行下一次解析舞台。
After having figured out the input, it is fairly easy to come up with gdb commands which will display all of the parsing
stages:
在计算出输入之后,可以很容易地找到GDB命令,这些命令将显示所有的解析阶段:
break qcplgte
set pagination off
commands 1
silent
x/s *(uint64_t *)($rsi+0x8)
continue
end
Here's the short explanation of the commands above: According to x64 calling convention for System V the second
parameter is passed through the %rsi register. The pointer to the SQL text is stored in the memory location %rsi+8. The
OS is 64-bit, therefore casting to uint64_t when dereferencing %rsi+0x8. Finally, x/s will dereference the pointer to
the (sub)string which is stored on the memory location %rsi+0x8.
下面是对上面命令的简短解释:根据对SystemV的x64调用约定,第二个参数通过%RSI寄存器传递。指向SQL文本的指针存储在内存位置
%rsi 8中。操作系统为64位,因此当取消引用%rsi 0x8时,转换为uint 64_t。最后,x/s将取消指向存储在内存位置%rsi 0x8上的(子)字
符串的指针。
--//注:里面的翻译我直接拿金山词霸翻译的.可能不是很准确.
--//我并不感兴趣作者遇到的Memory Leak问题.而是使用跟踪qcplgte看到的输出.自己也测试看看:
1.环境:
SCOTT@book> @ ver1
PORT_STRING VERSION BANNER
------------------------------ -------------- --------------------------------------------------------------------------------
x86_64/Linux 2.4.xx 11.2.0.4.0 Oracle Database 11g Enterprise Edition Release 11.2.0.4.0 - 64bit Production
$ cat parse.gdb
break qcplgte
set pagination off
commands 1
silent
x/s *(uint64_t *)($rsi+0x8)
continue
end
--//分析scott.dept表.略.重启数据库.
2.建立测试环境:
--//窗口1:
SCOTT@book> @ spid
SID SERIAL# PROCESS SERVER SPID PID P_SERIAL# C50
---------- ---------- ------------------------ --------- ------ ------- ---------- --------------------------------------------------
295 5 34816 DEDICATED 34817 21 3 alter system kill session '295,5' immediate;
--//记下spid=34817
--//窗口2:
$ gdb -p 34817 -x parse.gdb
GNU gdb (GDB) Red Hat Enterprise Linux (7.0.1-45.el5)
Copyright (C) 2009 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law. Type "show copying"
and "show warranty" for details.
This GDB was configured as "x86_64-redhat-linux-gnu".
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>.
Attaching to process 34817
...
3.测试1:
--//窗口1:
SCOTT@book> select/*+this is a test*/* from dept;
--//挂起.
--//窗口2:
Continuing.
0x7fff2e05d9c8: "select/*+this is a test*/* from dept"
0x7fff2e05d9ce: "/*+this is a test*/* from dept"
0x7fff2e05d9d1: "this is a test*/* from dept"
0x7fff2e05d9d5: " is a test*/* from dept"
0x7fff2e05d9e1: "* from dept"
0x7fff2e05d9e2: " from dept"
0x7fff2e05d9e7: " dept"
0x7fff2e05d9ec: ""
0x7fcbb40a8100: "select/*+this is a test*/* from dept"
0x7fcbb40a8106: "/*+this is a test*/* from dept"
0x7fcbb40a8119: "* from dept"
0x7fcbb40a811a: " from dept"
0x7fcbb40a811f: " dept"
0x7fcbb40a8124: ""
0x7fcbb40a8090: "SELECT /*+THISISATEST*/ * FROM DEPT"
0x7fcbb40a8096: " /*+THISISATEST*/ * FROM DEPT"
0x7fcbb40a80a9: " FROM DEPT"
0x7fcbb40a80ae: " DEPT"
--//很奇怪看到3组,第1组占8行也就是调用函数qcplgte8次.好像在逐步分解.而第2次调用函数qcplgte6次.这个用语言不好表达,慢慢理解吧.
--//实际上语句越复杂,第1组看到的调用函数qcplgte次数越多.原始链接有1个例子,大家可以自行测试.
--//而第3组是全部换成大写,注解部分发生了合并,删除了空格.
--//窗口1,如果再次执行相同语句.窗口2不会有输出,因为第2次执行是软解析.
SCOTT@book> select/*+this is a test*/* from dept;
4.测试2:
--//窗口1:
SCOTT@book> select/*+this is a test*/* from scott.dept ;
DEPTNO DNAME LOC
---------- -------------- -------------
10 ACCOUNTING NEW YORK
20 RESEARCH DALLAS
30 SALES CHICAGO
40 OPERATIONS BOSTON
--//加入shaema看看.
--//窗口2:
0x7fff2e05d9c0: "select/*+this is a test*/* from scott.dept "
0x7fff2e05d9c6: "/*+this is a test*/* from scott.dept "
0x7fff2e05d9c9: "this is a test*/* from scott.dept "
0x7fff2e05d9cd: " is a test*/* from scott.dept "
0x7fff2e05d9d9: "* from scott.dept "
0x7fff2e05d9da: " from scott.dept "
0x7fff2e05d9df: " scott.dept "
0x7fff2e05d9e5: ".dept "
0x7fff2e05d9e6: "dept "
0x7fff2e05d9ea: " "
0x7fcbb40a8108: "select/*+this is a test*/* from scott.dept "
0x7fcbb40a810e: "/*+this is a test*/* from scott.dept "
0x7fcbb40a8121: "* from scott.dept "
0x7fcbb40a8122: " from scott.dept "
0x7fcbb40a8127: " scott.dept "
0x7fcbb40a812d: ".dept "
0x7fcbb40a812e: "dept "
0x7fcbb40a8132: " "
0x7fcbb40a8090: "SELECT /*+THISISATEST*/ * FROM SCOTT . DEPT"
0x7fcbb40a8096: " /*+THISISATEST*/ * FROM SCOTT . DEPT"
0x7fcbb40a80a9: " FROM SCOTT . DEPT"
0x7fcbb40a80ae: " SCOTT . DEPT"
0x7fcbb40a80b4: " . DEPT"
0x7fcbb40a80b6: " DEPT"
--//发现一个很有趣的情况注意看第3组的输出,schema.tablename中间有空格.
--//我打开另外的窗口3执行如下:
--//窗口3:
SYS@book> select * from scott . dept where deptno=10;
DEPTNO DNAME LOC
---------- -------------- -------------
10 ACCOUNTING NEW YORK
--//也就是如上写法也是能执行成功的.
4.测试3:
--//突然想起我们许多情况应用使用大量文字变量,设定cursor_sharing=force的情况.测试看看这种情况如何解析.
--//窗口1:
SCOTT@book> alter session set cursor_sharing=force ;
Session altered.
SCOTT@book> select * from dept where deptno=10;
DEPTNO DNAME LOC
---------- -------------- -------------
10 ACCOUNTING NEW YORK
--//窗口2:
0x7fff9d820208: "select * from dept where deptno=10"
0x7fff9d82020e: " * from dept where deptno=10"
0x7fff9d820210: " from dept where deptno=10"
0x7fff9d820215: " dept where deptno=10"
0x7fff9d82021a: " where deptno=10"
0x7fff9d820220: " deptno=10"
0x7fff9d820227: "=10"
0x7fff9d820228: "10"
0x7fff9d82022a: ""
0x7dc4a338: "select * from dept where deptno=:\"SYS_B_0\""
0x7dc4a33e: " * from dept where deptno=:\"SYS_B_0\""
0x7dc4a340: " from dept where deptno=:\"SYS_B_0\""
0x7dc4a345: " dept where deptno=:\"SYS_B_0\""
0x7dc4a34a: " where deptno=:\"SYS_B_0\""
0x7dc4a350: " deptno=:\"SYS_B_0\""
0x7dc4a357: "=:\"SYS_B_0\""
0x7dc4a351: "deptno=:\"SYS_B_0\""
0x7dc4a357: "=:\"SYS_B_0\""
0x7dc4a358: ":\"SYS_B_0\""
0x7dc4a359: "\"SYS_B_0\""
0x7dc4a362: ""
0x7f0cb4e28108: "select * from dept where deptno=:\"SYS_B_0\""
0x7f0cb4e2810e: " * from dept where deptno=:\"SYS_B_0\""
0x7f0cb4e28110: " from dept where deptno=:\"SYS_B_0\""
0x7f0cb4e28115: " dept where deptno=:\"SYS_B_0\""
0x7f0cb4e2811a: " where deptno=:\"SYS_B_0\""
0x7f0cb4e28120: " deptno=:\"SYS_B_0\""
0x7f0cb4e28127: "=:\"SYS_B_0\""
0x7f0cb4e28128: ":\"SYS_B_0\""
0x7f0cb4e28129: "\"SYS_B_0\""
0x7f0cb4e28132: ""
0x7f0cb4e28090: "SELECT * FROM DEPT WHERE DEPTNO = :\"SYS_B_0\""
0x7f0cb4e28096: " * FROM DEPT WHERE DEPTNO = :\"SYS_B_0\""
0x7f0cb4e28098: " FROM DEPT WHERE DEPTNO = :\"SYS_B_0\""
0x7f0cb4e2809d: " DEPT WHERE DEPTNO = :\"SYS_B_0\""
0x7f0cb4e280a2: " WHERE DEPTNO = :\"SYS_B_0\""
0x7f0cb4e280a8: " DEPTNO = :\"SYS_B_0\""
0x7f0cb4e280af: " = :\"SYS_B_0\""
0x7f0cb4e280b1: " :\"SYS_B_0\""
0x7f0cb4e280b3: "\"SYS_B_0\""
0x7de1bdd6: "DEPTNO"
0x7de1bddc: ""
0x7db9aad6: "DNAME"
0x7db9aadb: ""
0x7db9a9fe: "LOC"
0x7db9aa01: ""
--//看到4组,仔细观察可以发现前面2组与第一次测试一样.我觉得真正分析的是第3次.
--//还很奇怪的是这样的情况还看到表dept中3个字段的分析调用.
--//窗口3:
SCOTT@book> show parameter cursor_sharing
NAME TYPE VALUE
-------------- ------ ------
cursor_sharing string EXACT
SCOTT@book> select * from dept where deptno=30;
DEPTNO DNAME LOC
---------- -------------- -------------
30 SALES CHICAGO
--//切换会窗口1,执行相同语句:
SCOTT@book> select * from dept where deptno=30;
DEPTNO DNAME LOC
---------- -------------- -------------
30 SALES CHICAGO
--//窗口2看到的输出:
0x7fff9d820208: "select * from dept where deptno=30"
0x7fff9d82020e: " * from dept where deptno=30"
0x7fff9d820210: " from dept where deptno=30"
0x7fff9d820215: " dept where deptno=30"
0x7fff9d82021a: " where deptno=30"
0x7fff9d820220: " deptno=30"
0x7fff9d820227: "=30"
0x7fff9d820228: "30"
0x7fff9d82022a: ""
0x7de1bdd6: "DEPTNO"
0x7de1bddc: ""
0x7db9aad6: "DNAME"
0x7db9aadb: ""
0x7db9a9fe: "LOC"
0x7db9aa01: ""
--//你可以看出因为别的会话在cursor_sharing=EXACT执行1次select * from dept where deptno=30;.
--//这样在cursor_sharing=force的会话执行select * from dept where deptno=30;仅仅分析1组.
--//窗口1:
SCOTT@book> select * from dept where deptno=40;
DEPTNO DNAME LOC
---------- -------------- -------------
40 OPERATIONS BOSTON
--//窗口2看到的输出:
0x7fff9d820208: "select * from dept where deptno=40"
0x7fff9d82020e: " * from dept where deptno=40"
0x7fff9d820210: " from dept where deptno=40"
0x7fff9d820215: " dept where deptno=40"
0x7fff9d82021a: " where deptno=40"
0x7fff9d820220: " deptno=40"
0x7fff9d820227: "=40"
0x7fff9d820228: "40"
0x7fff9d82022a: ""
0x7de1bdd6: "DEPTNO"
0x7de1bddc: ""
0x7db9aad6: "DNAME"
0x7db9aadb: ""
0x7db9a9fe: "LOC"
0x7db9aa01: ""
--//可以看到跟前面一样的情况.
--//可以看出cursor_sharing=force的情况下,只要存在文字变量,要调用qcplgte 1组,以消耗一定cpu资源为前提的.
[20191122]oracel SQL parsing function qcplgte.txt的更多相关文章
- [20191125]oracel SQL parsing function qcplgte 2.txt
[20191125]oracel SQL parsing function qcplgte 2.txt --//参考前面的测试:http://blog.itpub.net/267265/viewspa ...
- [20190328]简单探究sql语句相关mutexes.txt
[20190328]简单探究sql语句相关mutexes.txt --//摘要:http://www.askmaclean.com/archives/understanding-oracle-mute ...
- [20191101]通过zsh计算sql语句的sql_id.txt
[20191101]通过zsh计算sql语句的sql_id.txt 1.简单介绍以及测试使用zsh遇到的问题:--//前段时间写的,链接http://blog.itpub.net/267265/vie ...
- [20191011]通过bash计算sql语句的sql_id.txt
[20191011]通过bash计算sql语句的sql_id.txt --//当我知道如何通过bash计算sql语句的full_hash_value ,就很想通过bash编程计算sql_id.当时受限 ...
- SQL LOADER 的用法 TXT文件导入非常之快
前提,需要本地安装ORACLE 客户端 控制文件 cms.ctl load dataCHARACTERSET UTF8infile 'oracle.txt'APPEND INTO TABLE JR f ...
- sql连着function使用
create function fun002(@thename varchar()) returns int as begin declare @count int select @count=cou ...
- oracel SQL多表查询优化
SQL优化 1.执行路径:ORACLE的这个功能大大地提高了SQL的执行性能并节省了内存的使用:我们发现,单表数据的统计比多表统计的速度完全是两个概念.单表统计可能只要0.02秒,但是2张表联合统计就 ...
- oracel sql分组求和过滤条件
- 在数据库中生成txt文件到网络驱动器中(计算机直接创建的网络驱动器在sql server中没有被找到)
环境:sql server 2008 一.创建网络驱动器映射 语法:exec master..xp_cmdshell 'net use Z: \\ip地址\网络路径 密码 /user:用户名' 例如: ...
随机推荐
- iOS Core Animation 简明系列教程
iOS Core Animation 简明系列教程 看到无数的CA教程,都非常的难懂,各种事务各种图层关系看的人头大.自己就想用通俗的语言翻译给大家听,尽可能准确表达,如果哪里有问题,请您指出我会尽 ...
- cf1119d Frets On Fire 前缀和+二分
题目:http://codeforces.com/problemset/problem/1119/D 题意:给一个数n,给出n个数组的第一个数(a[0]=m,a[1]=m+1,a[2]=m+2,... ...
- 2017 CCPC秦皇岛 H题 Prime set
Given an array of integers , we say a set is a prime set of the given array, if and is prime. Ba ...
- 【译】Visual Studio 2019 中 WPF & UWP 的 XAML 开发工具新特性
原文 | Dmitry 翻译 | 郑子铭 自Visual Studio 2019推出以来,我们为使用WPF或UWP桌面应用程序的XAML开发人员发布了许多新功能.在本周的 Visual Studio ...
- HTML中用AJAX方式把数据存储到浏览器中并取出
把对象只有转成字符串形式才可以存入,取出则是把字符串转成对象
- 大数据学习笔记——HDFS写入过程源码分析(2)
HDFS写入过程注释解读 & 源码分析 此篇博客承接上一篇未讲完的内容,将会着重分析一下在Namenode获取到元数据后,具体是如何向datanode节点写入真实的数据的 1. 框架图展示 在 ...
- 一篇文章搞清楚HashMap和TreeMap的内部结构
一.HashMap 1.基于哈希表的 Map 接口的实现. 此实现提供所有可选的映射操作,并允许使用 null 值和 null 键.(除了非同步和允许使用 null 之外,HashMap 类与 Has ...
- 真伪随机数 ——Random和SecureRandom
Random Random用来创建伪随机数.所谓伪随机数,是指只要给定一个初始的种子,产生的随机数序列是完全一样的. 要生成一个随机数,可以使用nextInt().nextLong().nextFlo ...
- 《Java基础知识》Java类的定义及其实例化
类必须先定义才能使用.类是创建对象的模板,创建对象也叫类的实例化. 下面通过一个简单的例子来理解Java中类的定义: public class Dog { String name; int age; ...
- 【Springboot】用Springboot Admin监控你的微服务应用
1 简介 目前,微服务大行其道,各大小公司争相学习模仿,把单体应用拆得七零八落.服务多了,运行的实例多了,给运维人员的压力就更大了.如果有十几个应用,单单做Health Check就已经够费时间的了. ...