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.mzph.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…