MySQL处理sql语句过程

在MySQL中,将客户端请求分为了两种类型:
一种是query,需要调用Parser也就是Query解析和转发模块的解析才能够执行的请求;
一种是command,不需要调用Parser就可以直接执行的请求;

当客户端请求和连接线程“互换暗号(互通协议)”接上头之后,连接线程就开始处理客户端请求发送过来的各种命令(或者query),接受相关请求。

连接线程将收到的query语句转给Query解析和转发模块,Query解析器先对Query进行基本的语义和语法解析,然后根据命令类型的不同,有些会直接处理,有些会分发给其他模块来处理。

如果是一个Query类型的请求,会将控制权交给Query解析器。Query解析器首先分析看是不是一个select类型的query,如果是,则调用查询缓存模块,让它检查该query在query cache中是否已经存在。如果有,则直接将cache中的数据返回给连接线程模块,然后通过与客户端的连接的线程将数据传输给客户端。如果不是一个可以被cache的query类型,或者cache中没有该query的数据,那么query将被继续传回query解析器,让query解析器进行相应处理,再通过query分发器分发给相关处理模块。

如果解析器解析结果是一条未被cache的select语句,则将控制权交给Optimizer,也就是Query优化器模块,如果是DML或者是DDL语句,则会交给表变更管理模块,如果是一些更新统计信息、检测、修复和整理类的query则会交给表维护模块去处理,复制相关的query则转交给复制模块去进行相应的处理,请求状态的query则转交给了状态收集报告模块。实际上表变更管理模块根据所对应的处理请求的不同,是分别由insert处理器、delete处理器、update处理器、create处理器,以及alter处理器这些小模块来负责不同的DML和DDL的。

在各个模块收到Query解析与分发模块分发过来的请求后,首先会通过访问控制模块检查连接用户是否有访问目标表以及目标字段的权限,如果有,就会调用表管理模块请求相应的表,并获取对应的锁。表管理模块首先会查看该表是否已经存在于table cache中,如果已经打开则直接进行锁相关的处理,如果没有在cache中,则需要再打开表文件获取锁,然后将打开的表交给表变更管理模块。

当表变更管理模块“获取”打开的表之后,就会根据该表的相关meta信息,判断表的存储引擎类型和其他相关信息。根据表的存储引擎类型,提交请求给存储引擎接口模块,调用对应的存储引擎实现模块,进行相应处理。

不过,对于表变更管理模块来说,可见的仅是存储引擎接口模块所提供的一系列“标准”接口,底层存储引擎实现模块的具体实现,对于表变更管理模块来说是透明的。他只需要调用对应的接口,并指明表类型,接口模块会根据表类型调用正确的存储引擎来进行相应的处理。

当一条query或者一个command处理完成(成功或者失败)之后,控制权都会交还给连接线程模块。如果处理成功,则将处理结果(可能是一个Result set,也可能是成功或者失败的标识)通过连接线程反馈给客户端。如果处理过程中发生错误,也会将相应的错误信息发送给客户端,然后连接线程模块会进行相应的清理工作,并继续等待后面的请求,重复上面提到的过程,或者完成客户端断开连接的请求。

如果在上面的过程中,相关模块使数据库中的数据发生了变化,而且MySQL打开了bin-log功能,则对应的处理模块还会调用日志处理模块将相应的变更语句以更新事件的形式记录到相关参数指定的二进制日志文件中。

在上面各个模块的处理过程中,各自的核心运算处理功能部分都会高度依赖整个MySQL的核心API模块,比如内存管理,文件I/O,数字和字符串处理等等。