mysql 源碼 緩存_MySQL源碼:MYSQL存儲過程/函數的分析原理及緩存機制

前言:我個人認為,有關MYSQL存儲過程/函數在MYSQL中的實現比較粗糙,可擴展性不夠好,其實現的耦合性太高,所以主要講一些它的原理方面的內容,但有可能在某些方面理解不夠好或者有些不正確的地方,歡迎指正,謝謝!

2012-5-14 by whuai QQ:329570985 歡迎指正!

在MYSQL中,同樣有很多類型的系統對象,包括表、視圖、存儲過程、存儲函數等,但由于MYSQL的插件式存儲引擎及其它實現方面的特點,其每一種對象的緩存方式都不同,或者說這些對象的緩存不是通過一種統一的方式來管理的,每一種對象的緩存都是有自己的特點,并且緩存的內容也有很大的差異,下面再敘述一下存儲過程(PLSQL)緩存方式。

MYSQL數據庫管理系統中的存儲過程/函數也是有緩存機制的,存儲過程/函數實際上是用戶通過創建存儲過程的語句創建好的系統對象,它具有指定的名字、類型(存儲過程/函數)及要執行的語句序列等。例如下面就是一個創建過程的語句:

create procedure p()

begin declare a int default 100;

declare b int default 1000;

declare d int default 1000;

begin

declare c varchar(100) default 'hello world';

insert into my values(a, c);

end;

end;

上面創建的過程名字為p,下面定義了一些變量并且都賦了初始值,一對BEGIN及END標志了一個語句塊的內容,語句塊可以嵌套定義,比如上面就在第一對BEGIN及END之間又定義了一對BEGIN及END,每一個語句塊中又可以單獨定義自己的變量,同時這些變量又有自己的可見性范圍,假設在內層語句塊中定義了一個變量,在外層同時又定義了一個同名的變量,那么在內層引用這個變量時實際上是內層定義的變量,而這個變量在外層是不可見的,可以引用到的只能是外層定義的變量。

在實現上(基于源代碼的分析),一個存儲過程/函數分析后會得到一個sp_head結構體對象,這個對象唯一對應一個存儲過程,而每一個語句塊對應一個sp_pcontext結構對象,這個對象之間存在著父子關系,一個父親可以有多個孩子,一個孩子只能有一個父親,比如上面例子中的存儲過程語句,整體的存儲過程P就對應一個sp_head結構體對象,第一個BEGIN對應的語句塊是父sp_pcontext,而其中又包括了一個語句塊,這個語句塊是父語句塊的一個子語句塊,在分析之后同樣會生成一個sp_pcontext對象,它是一個子語句塊對象,sp_pcontext結構體內有一個成員m_parent,它會指向父語句塊,實際上這個語句塊可以被稱為一個“上下文環境”,因為它是可以被看作像C語言中的一個語句塊,比如用{}括起來的一段代碼一樣。

在進行語法分析sp_compile時,MYSQL會對每一條分析的語句都生成相應的指令,這些指令都被順序存儲到類型為DYNAMIC_ARRAY的動態數組m_instr中,這是用來存儲所有的這個存儲過程的指令的,比如對于上面語句“declare b int default 1000;”,系統首先會分配一個變量的存儲空間,變量被放在sp_pcontext對象中,也是通過一個動態數組m_vars來存儲的,因為變量是語句塊級的,而上面這條語句還對應的一個操作就是給這個變量賦初始值,所以系統要創建一個指令給這個變量設置初值,這個指令為sp_instr_set,每一個指令都需要實現一個執行函數exec_core,這個函數是一個虛函數,每一種指令的執行都要實現自己的執行函數,就比如上面這個設置變量的指令,它的實現是調用了函數set_variable來給指定的變量設置指定的初始值即可。

對于不同的操作,有不同的指令,MYSQL包括的指令有:sp_instr_stmt(執行SQL語句的指令)、sp_instr_set(設置變量的指令)、sp_instr_set_trigger_field(設置觸發器中涉及到NEW/OLD變量的值的指令)、sp_instr_jump、sp_instr_jump_if_not(執行跳轉指令)、sp_instr_freturn(函數返回指令)、sp_instr_cpush(游標聲明指令)、sp_instr_copen(打開游標的指令)、sp_instr_cclose(關閉游標的指令)、sp_instr_cfetch(從游標取數據的指令)等,在PLSQL中涉及到這些操作后,都會創建相應的指令,并加入到sp_head的指令動態數組中,執行時會通過順序或者跳轉的方式執行。

在PLSQL中,本人最感興趣的是變量的引用,包括本地變量及上層語句塊的變量的引用,系統是如何正確的找到相應的變量的?或者是通過什么方式來找到的?其實sp_head中的每一個變量都對應一個編號,是按照分析順序生成的。變量是在sp_pcontext中定義的,也就是說變量的存儲單元是語句塊(sp_pcontext),一個語句塊中可以有多個變量。同時在每一個語句塊結構體sp_pcontext中都有一個表示這個語句塊中所定義的變量的編號的范圍,一個起始ID及變量個數,因為sp_pcontext是按照父子關系來聯系的,那么一個語句塊的開始變量ID號是其前面平行的語句塊的開始ID號加1的值,如果它本身就是第一個語句塊,則其起始語句塊的變量ID號為其父語句塊的結束ID號加1的值。所以這樣就給每一個語句塊指定了唯一的互不包含的變量ID號的范圍。

那么要引用一個變量時,找到其在符號表中的對象是很容易的,因為對每一個指令而言,都有一個指針指向其所屬的sp_pcontext,同時每一個引用變量操作對應的指令都記錄了這個變量的ID號,這樣系統可以直接根據sp_pcontext中的超始ID號及變量的個數計算出當前這個被引用的變量對應的ID號是否在當前語句塊sp_pcontext中,如果是則直接從sp_pcontext的變量動態數組m_vars中找到對應ID的變量對象,如果沒有找到,則說明這個變量有可能是在父語句塊中定義的,則通過sp_pcontext中的m_parent找到其父語句塊,用同樣的方法找對應的變量,如果找到則已,找不到繼續向上,依此類推,直到找到在某一個語句塊中的這個變量,或者m_parent為空的時候則說明沒有找到,則說明這個引用是一個對未定義的變量的引用,直接報錯即可。那么通過上面的方法只要找到這個變量對象,則對其訪問或者給它賦值,都可以直接訪問其成員函數即可。

由于PLSQL的數據類型及支持語句比較多,這里只介紹一些比較重要的原理,從上面所敘述的內容可以對PLSQL的分析、指令的生成及運行原理有一個大概的輪廓,從總的結構來講,存儲過程/函數生成的計劃就是一個sp_head對象,sp_head中包含了所有生成的指令,在運行過程中按照指令順序或者內部邏輯的跳轉來執行。另外生成一個語句塊的樹形結構,每一個樹節點為sp_pcontext結構對象,其中m_parent指向其父節點,同時每一個sp_pcontext還存儲了所有的子語句塊鏈表,PLSQL中定義的變量都存儲在sp_pcontext中。

本文還要講另外一個內容就是存儲過程/函數對象的緩存機制,其實在MYSQL中,緩存的并不是存儲過程/函數的字典定義的對象,也就是說不是像之前講的表對象的字典緩存,而是將整個分析好的sp_head對象緩存起來了。那么說白了,MYSQL的存儲過程/函數字典的緩存其實是其執行計劃的緩存。只要執行過一次,那么只要沒有將這個存儲過程/函數刪除,再次執行時只需要從緩存空間中找到這個計劃拿出來直接執行即可,這樣就提高了存儲過程/函數的執行效率,不需要再進行詞法、語法、語義、指令的生成等這些步驟了。

總結:在MYSQL中的存儲過程/函數的分析過程將上面提到的所有步驟都揉合到了一起,也就是說:詞法分析、語法分析、語義分析、指令的生成這些步驟的分析過程沒有一個階段性的區分,沒有明顯的區分各個階段的工作,而是將所有這些步驟都一起完成,每分析一條語句,詞法、語法做完之后,直接分析這條語句中的語義、判斷定義的變量是否存在、確定變量在語句塊中的位置,合法之后直接創建變量的空間,同時還要分配一個指令,為這個變量設置初始值等操作,所有這些直接在語法文件中完成了,在實現上難免非常混亂。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/445796.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/445796.shtml
英文地址,請注明出處:http://en.pswp.cn/news/445796.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

如何單元測試Java的private方法

問題 Java類中private方法通常只能被其所屬類的調用,其他類只能望而卻步,單元測試private方法也就一籌莫展。 嘗試解法: 在測試時,手動將private改為public,測試完后再將其改回。將測試方法寫進private方法的所屬類…

圖論與java_算法筆記_150:圖論之雙連通及橋的應用(Java)

1 問題描述DescriptionIn order to get from one of the F (1 < F < 5,000) grazing fields (which are numbered 1..F) to another field, Bessie and the rest of the herd are forced to cross near the Tree of Rotten Apples. The cows are now tired of often bein…

如何用JUnit單元測試List

問題 JUnit測試List時差強人意。 解法 引入依賴 hamcrest-library包含許多有用方法來測試List數據類型。 <dependencies><dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>4.12</version>&l…

java數據包解析_請教http請求數據包如何解析 重組

該樓層疑似違規已被系統折疊 隱藏此樓查看此樓下面是我捕獲到的請求報文片段dst_ip:/121.52.228.134ack:trueack_num:3064957366date:POST /messagebroker/amf HTTP/1.1Host: s16.xxhzw.game.yy.comUser-Agent: Mozilla/5.0 (Windows NT 5.1; rv:13.0) Gecko/20100101 Firefox/…

webqq java_WebQQ登錄詳解

第二次登錄請求方式:POST地址:http://d.web2.qq.com/channel/login2POST正文:r%7B%22status%22%3A%22online%22%2C%22ptwebqq%22%3A%22{0}%22%2C%22passwd_sig%22%3A%22%22%2C%22clientid%22%3A%22{1}%22%2C%22  psessionid%22%3Anull%7D&clientid{2}&psessionidnull…

LeetCode - Easy - 155. Min Stack

Topic StackDesign Description https://leetcode.com/problems/min-stack/ Design a stack that supports push, pop, top, and retrieving the minimum element in constant time. push(x) – Push element x onto stack.pop() – Removes the element on top of the st…

java judgefilecode_VScode出現無法打開“X”: 找不到文件(file:///XXXX) 的解決辦法

如標題&#xff0c;被這個問題整了好長時間了&#xff0c;調試的時候如果有語法錯誤只能顯示相應的的行數&#xff0c;沒有辦法定位到出錯的行數上。(由于用處不是很大并且沒有找到解決辦法&#xff0c;所以就一直放著沒管23333)直到最近看到一位大佬的解決辦(重寫正則表達式)法…

LeetCode - Easy - 169. Majority Element

Topic ArrayDivide and ConquerBit Manipulation Description https://leetcode.com/problems/majority-element/ Given an array of size n, find the majority element. The majority element is the element that appears more than ? n/2 ? times. You may assume t…

java 靜態方法 異常_java空指針異常與靜態方法

從一道經典面試題說起&#xff0c;public class HaHa {public static void haha(){System.out.println("haha");}public static void main(String[] args){((HaHa)null).haha();}}打印結果 haha。這段題考查兩點知識&#xff0c;java的空指針異常和靜態方法。1&#…

java中的asList_Java中的Arrays.asList()方法

Arrays.asList()返回一個List&#xff0c;但是這種情況下&#xff0c;其底層的實現是一個final數組&#xff0c;因此不能調整其尺寸如下代碼片段&#xff1a;package chapter11.t1;import java.util.*;public class AddingGroups {public static void main(String[] args) {Lis…

java控制面板作用_Java

1. JAVA 的特性和優勢(1) Java的核心優勢 跨平臺/可移植性(2) 其他特性 安全性&#xff1b;面對對象&#xff1b;簡單性&#xff1b;高性能&#xff1b;分布式&#xff1b;多線程&#xff1b;健壯性&#xff1b;① 強大的生態系統(3) Java與C的關系 Java是C的簡化版(C—)2. JAV…

java es 數據批量導入_ElasticSearch—Java批量導入導出

網上找了很多&#xff0c;我的es是2.3.5版本&#xff0c;網上的客戶端最少都是5.x版本&#xff0c;所以沒有能用的。自己整合了一下 2.3.5版本的。pom文件&#xff1a;org.elasticsearchelasticsearch2.3.5com.alibabafastjson1.1.35org.apache.commonscommons-io1.3.2org.apac…

java原始模型模式_java設計模式--原始模型模式

簡介原始模型模式屬于對象的創建模式。通過一個原型對象來指明要創建對象的類型&#xff0c;然后用復制原型對象的方法來創建出更多同類型的對象。Java所有的類都是從java.lang.Object類繼承來的&#xff0c;Object類提供clone()方法對對象進行復制。一般調用clone()方法需要滿…

Windows的命令行窗口運行Python時,如何清屏?

問題 如標題 解法 import os os.system("cls")參考 python實現清屏

手寫文字識別java_java 手寫文字圖片識別提取 百度API

package org.fh.util;import org.json.JSONObject;import java.io.BufferedReader;import java.io.InputStreamReader;import java.net.HttpURLConnection;import java.net.URL;import java.util.List;import java.util.Map;/*** 說明&#xff1a;獲取文字識別token類* from&am…

LeetCode - Easy - 191. Number of 1 Bits

Topic Bit Manipulation Description https://leetcode.com/problems/number-of-1-bits/ Write a function that takes an unsigned integer and returns the number of ‘1’ bits it has (also known as the Hamming weight). Note: Note that in some languages such …

java并行計算同步返回_Java大文本并行計算實現過程解析

Java大文本并行計算實現過程解析簡單提高文本讀取效率&#xff0c;使用BufferedReader是個不錯的選擇。速度最快的方法是MappedByteBuffer&#xff0c;但是&#xff0c;相比BufferedReader而言&#xff0c;效果不是非常明顯。也就是說&#xff0c;后者雖然快&#xff0c;但也快…

wgs utm java,Java,將經緯度轉換為UTM

Does anyone know of a way, in Java, to convert an earth surface position from lat, lon to UTM (say in WGS84)? Im currently looking at Geotools but unfortunately the solution is not obvious.解決方案I was able to use Geotools 2.4 to get something that works…

java 指定時間轉換_Java中使用Calendar進行獲取指定時間,使用SimpleDateFormat進行格式化轉換...

java中使用Calendar獲取指定的時間public class DateTranslate {/*** 獲取指定日期的間隔月份的第一天的日期* param date* param sep* return*/public static Date getMonthFirstDay(Date date, Integer sep) {Calendar cal Calendar.getInstance();cal.setTime(getThisWeekM…

java mvc 菜鳥_【java框架】SpringMVC(1)--SpringMVC入門

1.SpringMVC框架認識Spring MVC是一個基于MVC模式的Web框架&#xff0c;SpringMVC作為Spring中的一個模塊&#xff0c;它與Spring能夠無縫集成&#xff0c;主要用于解決企業Web開發中常見的問題&#xff1a;如參數接收、文件上傳、表單驗證、國際化等等。2.SpringMVC HelloWorl…