当你执行一条SQL语句时是否有想过数据库的执行流程是怎么样的。了解数据库的工作流程有助于开发人员在日常的问题排查,接下来让我们来了解一下Mysql的基础架构。

Mysql数据库的基础结构大致可以分为业务层(server)和存储引擎两个部分,其中server层又包含了连接器、缓存、分析器、优化器、执行器五个部分,其涵盖了大多数Mysql的核心功能;而存储引擎是用来存储数据与数据的提取的,mysql的存储引擎采用的是插件式的,在你执行create table 时指定存储引擎默认为InnoDB(从mysql 5.5.5开始)。

MYSQL存储逻辑 mysql存储器_缓存


一、连接器

连接器的主要功能是负责跟客户端建立连接,用户权限的管理,维持和管理连接。

在客户端与数据库进行TCP三次握手之后,连接器开始认证用户身份,验证不通过则会返回:“Access denied for user” 的错误代码。验证通过的话就会去权限表里查询该用户的权限,这个连接之后的权限判断都根据这次查到的权限为依据。这就意味着,连接一旦建立,即使管理员对该用户的权限进行修改,也不会对当前连接的权限造成影响;所以修改权限后,只有再建立的新连接才会使用新的权限信息。

建立连接完成后,只要没有后续的操作,这个连接就会处于空闲状态,如果用户长时间没有对数据库进行操作,连接器会自动断开连接,这个时间由参数wait_timeout控制,默认值为8个小时。在连接断开以后,客户端再发生请求,就会收到一个:Lost connection to Mysql server during query 的提示。

对于连接的信息, 我们可以通过 show processlist 命令查看。

MYSQL存储逻辑 mysql存储器_缓存_02


在数据库中,连接分为长连接和短连接。长连接是指连接成功后,客户端持续请求 则会一直使用同一个连接。短连接是指在每次执行完请求以后就断开的连接。由于建立连接的过程比较复杂且耗费资源,建议使用长连接。但是全部使用长连接,有可能导致内存暴涨,被系统强行kill (OOM)。

对于 这种情况有两种解决方案:

1、定期断开长连接。设置一个时间定时清理连接或者在程序执行完一个占用内存大的请求后,断开连接。

2、在mysql5.7以后可以在每一次执行完一个比较大的操作之后 通过 执行:mysql_reset_connection 来重新初始化连接资源。

二、查询缓存
当你执行一条查询语句时,Mysql会到查询缓存中看看之前是否执行过这条语句。执行过的sql语句将会以key-value的形式存储在缓存中,key为sql语句,如果命中则直接返回结果,否则将继续下面的操作,查询结果也将会被存储在缓存中。
对于更新频繁的数据库来说,建议不要使用查询缓存。由于更新间隔短,你敢存储的缓存可能很快就被下一个更新给清空,缓存命中率低。
可能有些数据查询可能效率会比较高,这时你可以将 query_cache_type 设置为DEMAND(默认对sql语句禁用缓存)。然后使用SQL_CACHE显式指定,例如:

select SQL_CACHE * from user where userId=1;

ps:mysql 8.0已经没有查询缓存的功能。

三、分析器
在查询缓存没有命中时,sql语句将进入分析器。分析器首先会对sql语句进行词法分析,比如sql的关键字 select 时一条查询语句,然后识别 字符串“user”为表名称,“userId” 为列名。昨晚词法分析以后,就开始做语法分析。语法分析器会根据语法规则判断你的sql是否满足Mysql语法。如果你的语句不对,你将收到一条 “you have an error in your SQL syntax”。
四、优化器
优化器的只要功能是对sql语句的执行方案进行选择,为下面执行器对sql的执行做准备。比如,sql语句中存在多个索引,优化器将觉得需要哪个索引,jion多表时,优化器需要觉得执行的顺序等等。
五、执行器
在执行器执行sql时会进行权限验证,判断改连接是否有该表的权限。如果有权限,执行器就会根据该表的引擎定义,去使用这个引擎所提供的接口,执行sql。