[20191122]oracel SQL parsing function qcplgte.txt

来源:https://www.cnblogs.com/lfree/archive/2019/11/22/11909697.html
-Advertisement-
Play Games

[20191122]oracel SQL parsing function qcplgte.txt--//昨天看了鏈接:https://nenadnoveljic.com/blog/memory-leak-parsing/ =>Memory Leak During Parsingqcplgteqcp ...


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


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 1.我們使用緩存時的業務流程大概為: 當我們查詢一條數據時,先去查詢緩存,如果緩存有就直接返回,如果沒有就去查詢資料庫,然後返回。這種情況下就可能出現下麵的一些現象。 2.緩存穿透 2.1什麼是緩存穿透 緩存穿透是指查詢一個一定不存在的數據,由於緩存是不命中時被動寫的,並且出於容錯考慮,如果從存儲層 ...
  • 如果你的系統有高併發的要求,可以嘗試使用SQL Server記憶體優化表來提升你的系統性能。你甚至可以把它當作Redis來使用。 ...
  • 對比結論 1. 性能上: 性能上都很出色,具體到細節,由於Redis只使用單核,而Memcached可以使用多核,所以平均每一個核上Redis在存儲小數據時比Memcached性能更高。而在100k以上的數據中,Memcached性能要高於Redis,雖然Redis最近也在存儲大數據的性能上進行優化 ...
  • select * from table1 t where (select count(*) from table1 where column1=t.column1 AND column2=t.column2 and column3=t.column3)>1 ...
  • USE [SPECIAL_BLD]GO SET ANSI_NULLS ONGO SET QUOTED_IDENTIFIER ONGO CREATE FUNCTION [dbo].[get_upper] ( @num numeric(18,5))RETURNS VARCHAR(500)ASBEGIN ...
  • 一、Atlas是什麼? 在當今大數據的應用越來越廣泛的情況下,數據治理一直是企業面臨的巨大問題。 大部分公司只是單純的對數據進行了處理,而數據的血緣,分類等等卻很難實現,市場上也急需要一個專註於數據治理的技術框架,這時Atlas應運而生。 Atlas官網地址: "https://atlas.apac ...
  • 看如下一條sql語句: # table T (id int, name varchar(20)) delete from T where id = 10; MySQL在執行的過程中,是如何加鎖呢? 在看下麵這條語句: select * from T where id = 10; 那這條語句呢?其實這 ...
  • 在MySQL中經常出現未按照理想情況使用索引的情況,今天記錄一種Order by語句的使用導致未按預期使用索引的情況。 1. 問題現象 1.1 SQL語句: SELECT DISTINCT p.* FROM tb_name p WHERE 1=1 AND p.createDate >= '2019- ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...