一、mysql 逻辑架构概览
mysql 最重要、最与众不同的特性就是它的可插拔存储引擎架构(pluggable storage engine architecture),这种架构的设计将查询处理及其他系统任务和数据的存储/提取分离开来。来看官网的解释:
the mysql pluggable storage engine architecture enables a database professional to select a specialized storage engine for a particular application need while being completely shielded from the need to manage any specific application coding requirements.
大致意思就是,mysql 可插拔存储引擎架构使开发者能够为特定应用程序需求选择专门的存储引擎,同时完全无需管理任何特定应用程序编码要求。也就是说,尽管不同存储引擎具有不同的功能,但应用程序不受这些差异的影响。
如果应用程序更改带来了需要更改底层存储引擎的需求,或者需要添加一个或多个存储引擎来支持新需求,则无需进行重大的编码或流程更改即可使工作正常进行。 mysql 服务器架构通过提供适用于跨存储引擎的一致且易于使用的 api,使应用程序免受存储引擎底层复杂性的影响。
mysql 的逻辑架构图如下,参考《高性能 mysql - 第 3 版》:
我们可以大致把 mysql 的逻辑架构分成 server 层和存储引擎层:
1)大多数 mysql 的核心服务功能都在 server 层,包括连接,查询解析、分析、优化、缓存以及所有的内置函数(例如,日期、时间、数学和加密函数),所有跨存储引擎的功能都在这一层实现:存储过程、触发器、视图等。
值得一提的是,server 最上面的服务也就是连接器,拥有管理 mysql 连接、权限验证的功能。显然这并非 mysql 所独有,大多数基于网络的客户端/服务器的工具或者服务都有类似的架构。
2)第二层就是存储引擎(支持 innodb、myisam、memory 等多个存储引擎)。存储引擎负责 mysql 中数据的存储和提取,响应上层服务器的请求。每个存储引擎自然是有它的优势和劣势,不同的存储引擎之间无法相互通信,所以我们需要根据不同的场景来选择合适的存储引擎。
服务器通过 api 与存储引擎进行通信。这些接口屏蔽了不同存储引擎之间的差异,使得这些差异对上层的查询过程透明。存储引擎 api 包含几十个底层函数,用于执行诸如 “开始一个事务” 或者 “根据主键提取一行记录” 等操作。
需要注意的是,在 mysql 5.1 及之前的版本,myisam 是默认的存储引擎,而在 mysql 5.5.5 后,innodb 成为了默认的存储引擎。
二、连接器(connector)
mysql 5.7 的官方文档中,是这样描述连接器的:
mysql connectors provide connectivity to the mysql server for client programs.
mysql 连接器为客户端程序提供到 mysql 服务器的连接。 说得更细节一点的话,连接器其实会做两个事情,一个是管理 mysql 连接,一个是权限验证。我们依次来解释下。
首先,要连接到 mysql 服务器,我们通常需要提供 mysql 用户名和密码,并且如果服务器运行在我们登录的机器以外的机器上,还需要指定一个主机名比如 host。 所以连接命令一般是这样的:
shell> mysql -h host -u user -p
enter password: ********
mysql> 就是在提示你 mysql 已准备好了,你可以开始输入 sql 语句了!
当然,连接器做的事情不仅仅是比对一下用户名和密码,它还会验证该用户是否具有执行某个特定查询的权限(例如,是否允许该用户对 world 数据库的 country 表执行 select 语句)。之后,这个连接里面的所有权限判断逻辑,都将依赖于此时读到的权限。
这意味着,当一个用户成功建立连接后,即使你在另一个终端用管理员账号对这个用户的权限做了修改,对当前已经存在连接的权限不会造成任何影响。
也就是说,当修改了用户权限后,只有再新建的连接才会使用新的权限设置。
当一个连接建立起来后,如果你没有后续的动作,那么这个连接就处于空闲状态(sleep)。
事实上,对于一个 mysql 连接来说(或者说一个线程),任何时刻都有一个状态,该状态表示了 mysql 当前正在做什么。有很多种方式能查看当前的状态,最简单的是使用 show full processlist 命令(该命令返回结果中的 command 列就表示当前的状态)。
the query cache stores the text of a select statement together with the corresponding result that was sent to the client. if an identical statement is received later, the server retrieves the results from the query cache rather than parsing and executing the statement again. the query cache is shared among sessions, so a result set generated by one client can be sent in response to the same query issued by another client.