MySQL源码:MYSQL存储过程/函数的分析原理及缓存机制
2012-05-15 10:02:16 来源:WEB开发网核心提示:在PLSQL中,本人最感兴趣的是变量的引用,MySQL源码:MYSQL存储过程/函数的分析原理及缓存机制(2),包括本地变量及上层语句块的变量的引用,系统是如何正确的找到相应的变量的?或者是通过什么方式来找到的?其实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中的存储过程/函数的分析过程将上面提到的所有步骤都揉合到了一起,也就是说:词法分析、语法分析、语义分析、指令的生成这些步骤的分析过程没有一个阶段性的区分,没有明显的区分各个阶段的工作,而是将所有这些步骤都一起完成,每分析一条语句,词法、语法做完之后,直接分析这条语句中的语义、判断定义的变量是否存在、确定变量在语句块中的位置,合法之后直接创建变量的空间,同时还要分配一个指令,为这个变量设置初始值等操作,所有这些直接在语法文件中完成了,在实现上难免非常混乱。
更多精彩
赞助商链接