[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:用户名' 例如: ...
随机推荐
- Pandas学习(三)——NBA球员薪资分析
欢迎加入python学习交流群 667279387 学习笔记汇总 Pandas学习(一)–数据的导入 pandas学习(二)–双色球数据分析 pandas学习(三)–NAB球员薪资分析 pandas学 ...
- ZooKeeper初步
ZooKeeper 简介: 顾名思义 zookeeper 就是动物园管理员,他是用来管 hadoop(大象).Hive(蜜蜂).pig(小猪)的管理员, Apache Hbase 和 Apache S ...
- C++与数据结构课程设计---定票咨询系统
订票咨询管理系统 设计编制一个订票管理系统,考虑旅客不同的要求.例如,选择不同的交通工具,希望在旅途中的时间尽可能地短,期望旅费尽可能省,或要求中转次数最少等.为旅客提供两种或三种最优决策.车票基本信 ...
- 拓展KMP分析
拓展kmp是对KMP算法的扩展,它解决如下问题: 定义母串S,和字串T,设S的长度为n,T的长度为m,求T与S的每一个后缀的最长公共前缀,也就是说,设extend数组,extend[i]表示T与S[i ...
- 关于Java调用接入微信、支付宝支付提现
前言: 本篇文章介绍关于自己写的一个集成微信.支付宝的支付.提现等功能的介绍,本项目已在码云上进行开源,欢迎大家一起来进行改造,使进行更好的创新供大家使用:也有对应的pom文件坐标可以导入,因目前不知 ...
- spf13-vim 显示neocomplete requires ...th Lua support
安装spf13-vim的时候下载了许多插件,neocomplete应该是比较重要的一个,毕竟自动补全.但是在使用时却一直有:neocomplete requires ...th Lua support ...
- 2016/09/22 mapreduce
1.概念 Mapreduce是一个计算框架,表现形式是有个输入(input),mapreduce操作这个输入,通过本身定义好的计算模型,得到一个输出(output),也就是我们需要的结果. 在运行一个 ...
- linux指令-date
1.在linux中要显示日期,则可以直接输入指令date 2.如果想以这样2016/12/26的方式输出呢,那就是,Y是年份,m是月份,d是日 date +%Y/%m/%d 3.如果要显示时间,则da ...
- 百万级高并发mongodb集群性能数十倍提升优化实践
背景 线上某集群峰值TPS超过100万/秒左右(主要为写流量,读流量很低),峰值tps几乎已经到达集群上限,同时平均时延也超过100ms,随着读写流量的进一步增加,时延抖动严重影响业务可用性.该集群采 ...
- JDK1.8新特性-Lambda表达式
Lambda 表达式 Lambda 表达式,也可称为闭包,它是推动 Java 8 发布的最重要新特性. Lambda 允许把函数作为一个方法的参数(函数作为参数传递进方法中). 使用 Lambda 表 ...