本文从一个select语句的执行过程出发, 遍历MySQL的多个几子系统.

先放图一张, 按图索骥开始我们的历险.

<ignore_js_op>

 

当客户端连接上MySQL服务端之后,发出请求之前,服务端的线程是阻塞在do_command(sql/parse.cc)里的my_net_read函数中(就是socket里的read).

当客户端键入sql语句(本文例子select * from zzz)发送到服务端之后, my_net_read返回, 并从tcpbuffer中读取数据写入到packet这个字符串.

  1. packet_length= my_net_read(net);

复制代码

packet的第一个字节是个标志位, 决定数据包是查询还是命令,成功,或者出错。

接下来就进入dispatch_command(sql/sql/parse.cc)这个函数,数据类型不再需要.

  1. return_value= dispatch_command(command, thd, packet+1, (uint) (packet_length-1));

复制代码

进入dispatch_command, 我们可见

  1. statistic_increment(thd->status_var.questions, &LOCK_status);

复制代码

这个就是show status questions的值累加.

接下的mysql_parse(sql/sql_parse.cc), 该函数是sql语句解析的总路口.

进入该函数后首先碰到的是query_cache_send_result_to_client,故名思义这个函数是在QCache里查询是否有相同的语句, 有则立即从QCache返回结果, 于是整个sql就结束了.

QCache里不存在的sql则继续前进来到parse_sql(sql/sql_parse.cc),这个函数主要就是调用了MYSQLparse. 
而MYSQLparse其实就是bison/yacc里的yyparse(^_^),

  1. #define yyparse         MYSQLparse

复制代码

是的开始解析sql了. 关于词法分析和语法匹配简单说几下.

对于一条像select * from zzz的语句首先进入词法分析,找到2个token(select, from), 
然后根据token进行语法匹配, 规则在sql/yacc.yy里,

我把几个匹配到的pattern和action贴出来.

  1. select:
  2. select_init
  3. {
  4. LEX *lex= Lex;
  5. lex->sql_command= SQLCOM_SELECT;
  6. }
  7. ;
  8. /* Need select_init2 for subselects. */
  9. select_init:
  10. SELECT_SYM select_init2
  11. | '(' select_paren ')' union_opt
  12. ;
  13. select_paren:
  14. SELECT_SYM select_part2
  15. {
  16. LEX *lex= Lex;
  17. SELECT_LEX * sel= lex->current_select;
  18. .....
  19. select_from:
  20. FROM join_table_list where_clause group_clause having_clause
  21. opt_order_clause opt_limit_clause procedure_clause
  22. {
  23. Select->context.table_list=
  24. Select->context.first_name_resolution_table=
  25. (TABLE_LIST *) Select->table_list.first;
  26. }
  27. ....
  28. select_item_list:
  29. select_item_list ',' select_item
  30. | select_item
  31. | '*'
  32. {
  33. THD *thd= YYTHD;
  34. Item *item= new (thd->mem_root)
  35. Item_field(&thd->lex->current_select->context,
  36. NULL, NULL, "*");
  37. if (item == NULL)
  38. MYSQL_YYABORT;
  39. if (add_item_to_list(thd, item))
  40. MYSQL_YYABORT;
  41. (thd->lex->current_select->with_wild)++;
  42. }
  43. ;
  44. select_item:
  45. remember_name select_item2 remember_end select_alias
  46. {
  47. THD *thd= YYTHD;
  48. DBUG_ASSERT($1 < $3);
  49. if (add_item_to_list(thd, $2))
  50. MYSQL_YYABORT;
  51. if ($4.str)
  52. ...

复制代码

可以看到action里最关键的就是add_item_to_list 和table_list的赋值.
解析后对于需要查询的表(zzz)和字段(*)这些信息都写入到thd->lex这个结构体里了.

例如其中thd->lex->query_tables就是表(zzz)的状况, thd->lex->current_select->with_wild 是表示该语句是否使用了*等等.

  1. (gdb) p *thd->lex->query_tables
  2. $7 = {next_local = 0x0, next_global = 0x0, prev_global = 0x855a458, db = 0x85a16b8 "test", alias = 0x85a16e0 "zzz",
  3. table_name = 0x85a16c0 "zzz", schema_table_name = 0x0, option = 0x0, on_expr = 0x0, prep_on_expr = 0x0, cond_equal = 0x0,

复制代码

sql解析完了, 优化呢? 别急接着往下看.
接着进入mysql_execute_command函数,这个函数是所有sql命令的总入口.

由于是这个sql是一个select, 于是execute_sqlcom_select就是我们下个要执行的函数,
又然后进入了mysql_select(^_^怒了如此复杂).

mysql_select 就是优化器的模块, 这个模块代码比较复杂. 我们可以清楚看到创建优化器,优化,执行的3个步骤, 优化细节不表.

  1. if (!(join= new JOIN(thd, fields, select_options, result)))
  2. ...
  3. if ((err= join->optimize()))
  4. ...
  5. join->exec();

复制代码

结束了优化,我们要具体执行join->exec(), 该函数实际进入的是JOIN::exec()(sql_select.cc).

exec()首先向客户端发送字段title的函数send_fields, 没数据但字段也是要的.

然后再进入do_select(), 根据表的存储引擎跳入到引擎具体的实现(zzz是myisam).
这里mi_scan(info, buf) 就是myisam引擎扫描文件的函数,再看到info->filename=’./test/zzz’,不就是zzz表对应的物理文件吗.

通过一系列的mi函数访问磁盘拿到数据之后,会通过send_data发送数据给client,并从dispatch_command返回.最后在net_end_statement结束整个sql.

一个简单的select语句背后的执行过程是非常复杂的. 上面的步骤都只是点到就止.

ps: 在sql_yacc.yy可见MySQL对于Oracle中常用的dual表的嘲讽.

MYSQL SELECT 过程 转的更多相关文章

  1. Mysql加锁过程详解(4)-select for update/lock in share mode 对事务并发性影响

    Mysql加锁过程详解(1)-基本知识 Mysql加锁过程详解(2)-关于mysql 幻读理解 Mysql加锁过程详解(3)-关于mysql 幻读理解 Mysql加锁过程详解(4)-select fo ...

  2. MySQL关闭过程详解和安全关闭MySQL的方法

    MySQL关闭过程详解和安全关闭MySQL的方法 www.hongkevip.com 时间: -- : 阅读: 整理: 红客VIP 分享到: 红客VIP(http://www.hongkevip.co ...

  3. 24、jQuery常用AJAX-API/Java调用MySQL / Oracle过程与函数

      1)掌握jQuery常用AJAX-API 2)掌握Java调用MySQL / Oracle过程与函数 一)jQuery常用AJAX-API 目的:简化客户端与服务端进行局部刷新的异步通讯 (1)取 ...

  4. Mysql加锁过程详解(8)-理解innodb的锁(record,gap,Next-Key lock)

    Mysql加锁过程详解(1)-基本知识 Mysql加锁过程详解(2)-关于mysql 幻读理解 Mysql加锁过程详解(3)-关于mysql 幻读理解 Mysql加锁过程详解(4)-select fo ...

  5. Mysql加锁过程详解(9)-innodb下的记录锁,间隙锁,next-key锁

    Mysql加锁过程详解(1)-基本知识 Mysql加锁过程详解(2)-关于mysql 幻读理解 Mysql加锁过程详解(3)-关于mysql 幻读理解 Mysql加锁过程详解(4)-select fo ...

  6. mysql储存过程入门学习

    转载至:https://www.yiibai.com/mysql/getting-started-with-mysql-stored-procedures.html 1.mysql储存过程的创建 DE ...

  7. Mysql加锁过程详解(1)-基本知识

    Mysql加锁过程详解(1)-基本知识 Mysql加锁过程详解(2)-关于mysql 幻读理解 Mysql加锁过程详解(3)-关于mysql 幻读理解 Mysql加锁过程详解(4)-select fo ...

  8. Mysql加锁过程详解(2)-关于mysql 幻读理解

    Mysql加锁过程详解(1)-基本知识 Mysql加锁过程详解(2)-关于mysql 幻读理解 Mysql加锁过程详解(3)-关于mysql 幻读理解 Mysql加锁过程详解(4)-select fo ...

  9. Mysql加锁过程详解(3)-关于mysql 幻读理解

    Mysql加锁过程详解(1)-基本知识 Mysql加锁过程详解(2)-关于mysql 幻读理解 Mysql加锁过程详解(3)-关于mysql 幻读理解 Mysql加锁过程详解(4)-select fo ...

随机推荐

  1. kvm安装准备

    到实际情况下,做虚拟化是直接做在真机上. 但实验时,可以在虚拟机上进行.(因为做实验的时候没办法连接到桥接模式的网络,所以使用了NAT方式来连接网络) 在vmware安装centos 64bit fo ...

  2. POJ 2186 Popular cows(Kosaraju+强联通分量模板)

    题目链接:http://poj.org/problem?id=2186 题目大意:给定N头牛和M个有序对(A,B),(A,B)表示A牛认为B牛是红人,该关系具有传递性,如果牛A认为牛B是红人,牛B认为 ...

  3. gm(GraphicsMagick)图片中文水印乱码问题

    1.GraphicsMagick图片中文水印乱码问题处理方式 如出现乱码是由于服务器中缺少中文字库所致,为避免系统中存在多个中文字库冲突, 所以没有必要在安装GraphicsMagick时就将字库文件 ...

  4. 洛谷 P1957 口算练习题 题解

    题目传送门 这道题是考字符串处理,另外输入要使用c++的cin的神奇功能. #include<bits/stdc++.h> using namespace std; int n;char ...

  5. <<Javascript Patterns>>阅读笔记 – 第3章 字面量和构造函数

    对象字面量 首先给出对象字面量的定义语法: 1. 将对象定义在一对括号中(左大括号“{”和右大括号”}”) 2. 对象中以逗号分隔属性和方法. 每个属性或方法以key-value的形式出现, key和 ...

  6. 使用 JQuery 实现将 table 按照列排序

    使用 JQuery 实现将 table 按照列排序 使用 JQuery 实现将 table 按照列排序 代码如下 <!DOCTYPE html> <html> <head ...

  7. 【fastadmin】 _id 功能失效解决办法

    在add.html模版中修改对应的input标签的各种属性

  8. PHP实现插入排序

    插入排序思想: 插入排序(Insertion Sort)的算法描述是一种简单直观的排序算法. 它的工作原理是通过构建有序序列,对于未排序数据,在已排序序列中从后向前扫描, 找到相应位置并插入.插入排序 ...

  9. Python类总结-反射及getattr,setattr

    类反射的四个基本函数 hasattr getattr setattr delattr #反射 class BlackMedium: feature = 'Ugly' def __init__(self ...

  10. I/O 多路复用之select、poll、epoll详解

    select,poll,epoll都是IO多路复用的机制.I/O多路复用就是通过一种机制,一个进程可以监视多个描述符,一旦某个描述符就绪(一般是读就绪或者写就绪),能够通知程序进行相应的读写操作.但s ...