mysql各个模块如何协同工作的,我们通过启动mysql、客户端连接、请求query,得到返回结果,最后退出。这个过程来看一下。
执行启动mysql命令后,mysql的初始化模块从配置文件中读取系统参数与命令行参数,并按参数来初始化整个系统。同时各个存储引擎也被启动,并进行各自的初始化工作。
当整个系统初始化结束后,连接管理模块接手,连接管理模块启动处理客户端连接请求的监听程序,包括tcp/ip网络监听,还有unix的socket。此时mysql server基本启动完成,准备好接受客户端请求。
当连接管理模块监听到客户端的连接请求,双方通过client&server交互协议模块定义的协议“寒暄”几句后,连接管理模块将连接请求转给线程管理模块,去请求一个连接线程。
线程管理模块马上将控制交给连接线程模块,告诉连接线程模块:我这有连接请求,需要建立连接。连接线程模块接到连接请求后,首先检查当前线程连接池中是否有cache有空闲连接线程,如果有,取出一个和客户端请求连接,如果没有,则建立一个连接线程与客户端连接。当然连接线程模块并不是收到连接请求后马上取出连接线程与客户端连接,而是先调用用户模块进行授权检查,只有客户端请求通过了授权检查后,它才会将客户端请求与线程连接上。
在mysql中,客户端请求分为两种:一种是query,需要调用parser和转发模块才能执行的请求,一种是command,不需要调用parser就可以直接执行的请求。(如果在配置文件中打开了full query logging功能,那么query解析与转发模块会调用日志记录模块将请求记入日志,不管是一个query类型的请求还是一个command类型的请求,都会记录进入日志)
当客户端请求与连接线程接上头后,连接线程就开始处理客户端请求发送过来的各种命令或是query。它将收到的query转给query解析和转发模块,query解析器先对query进行基本的语义和语法解析,然后根据命令类型的不同,有些是直接处理,有些是转发给其他模块处理。
如果是一个query类型的请求,将控制权交给query解析器,query解析器首先分析是不是一个select,如果是,则调用查询缓存模块,让它检查该query在query cache中是否存在,如果有,则直接将cache中的数据返回给连接线程模块,然后再通过与客户端的连接线程将数据传输给客户端。如果没有,那query将传回query解析器,让query解析器进行相应处理,再通过query分发器转给相关处理模块。
如果解析器解析后的结果是一个未被cache的select,则将控制权交给optimizer,也就是query优化器模块。
如果是DML或是DDL,则交给表变更管理模块,
如果是一些更新统计信息、检测、修复和整理类的query则会交给表维护模块
复制相关的query则交给复制模块
请求状态的query交给状态收集报告模块
各个模块收到query解析与分发模块分为过来的请求后,首先通过访问控制模块检查连接用户是否有访问目标表以及字段的权限,如果有,调用表管理模块请求相应的表,并获取对应的锁。(表管理模块会查看该表是否在table cache中,如果已经打开则直接进行锁相关处理,如果不在cache,则需要打开表文件获取锁,然后将打开的表交给表管理模块)
当表变更管理模块获取打开的表后,根据该表的相关meta信息,判断表的存储引擎类型的其他相关信息,根据表的存储引擎类型,提交给存储引擎接口模块,调用对应的存储引擎实现模块,进行相应处理。(对于表变更管理模块来说,可见是仅是存储引擎所提供的一系列API,底层存储引擎实现模块的具体实现,对于表变更管理模块来说是透明的,它只需要调用对应的接口,指明表类型,接口模块表根据表类型调用正确存储引擎进行相应处理)
当一个query或是一个command处理完成(成功是失败)后,控制权都会交给连接线程模块。如果处理成功,则将处理结果通过连接线程返回给客户端,如果处理失败,也会将相应的错误信息发送给客户端,然后连接线程模块会进行相应的清理工作,并继续等待后面的请求,重复上面提到的过程,或是完成客户端断开连接的请求。
如果上面过程中,相关模块使数据库中的数据发生成了变化,而且mysql打开了binlog,则对应的处理模块会调用日志处理模块将相应的变更语句以更新事件的形式记录到相关参数指定的二进制日志文件中。
在上面各个模块处理过程中,各自的核心运算处理功能部分都高度依赖整个mysql的核心API模块,比如:内存管理、文件i/o、数字和字符串处理等等。
整理自:MySQL性能调优与架构设计 第二章 mysql架构组成