[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資源爲前提的.

html

相關文章
相關標籤/搜索