MySQL如何完成一次查询?
MySQL相信大家都不陌生,是一种关系型数据库,通过sql语言操作数据的增删改查。那么从发出一条sql指令到返回结果mysql都做了什么事情呢?
mysql完成一次查询过程是比较复杂的,在说明查询过程前先介绍一下它的基础概念和结构原理来帮助理解。下面从四个方面介绍,分别是mysql语句,mysql结构原理,mysql查询过程,最后设置几个有趣问题。
mysql的最基础使用是通过一条sql语句查询数据,sql语句在不同场景下存在着多种说法,主要根据执行语句的第一个关键字确定概念:
DDL(Data Definition Languages):数据定义语句,常用的语句关键字主要包括 create、drop、alter等操作表结构
DML(Data Manipulation Language):数据操作语句,常用的语句关键字主要包括 insert、delete、udpate 和select 等操作数据
DCL(Data Control Language):数据控制语句,用户的访问权限和安全级别。主要的语句关键字包括 grant、revoke 等
个人做项目或者学习时这些语句都可以随意执行,因为自己是管理员拥有最高权限。但是大部分场景是在公司使用,上面的SQL语句在特殊场景下自己是没有权限执行的,甚至只能执行select查询操作。
可以通过 grant 语句赋予数据库表具有不同等级的权限,下面举例:给指定用户只分配 select 权限
-- 创建用户(指定任何IP的ttk用户登录,密码是aa123456,%代表任何IP)
create user 'ttk'@'%' identified by 'aa123456';
-- 查看权限(查询任何IP下ttk用户的权限)
show grants for 'ttk'@'%';
-- 分配权限(给ttk用户在任何IP下可以访问所有数据库的表,*.*第一个星号是匹配所有库,第二个星号是匹配所有表,select是只有select权限)
grant select on *.* to 'ttk'@'%';
-- 如果需要拥有update权限
grant select, update on *.* to 'ttk'@'%';
通过上面语句赋予ttk用户查询权限,再次执行 update 和 insert 语句就会报权限异常错误
通过 revoke 语句把select权限也去掉
-- 取消权限(取消ttk用户对所有IP的所有数据库的所有权限)
-- all匹配所有权限,例如update,select等
-- *.*匹配所有数据库所有表
-- %匹配所有IP
revoke all on *.* from 'ttk'@'%';
再次执行select语句也会报权限错误
了解了mysql的基本语法,不同语句又可以概括为DDL、DML、DCL,本章介绍mysql的结构原理,下图是一个mysql引擎的原理图
连接者(Connectors):不同语言的代码程序和mysql的交互(SQL交互)
连接池(Connection Pool):管理、缓冲用户的连接,线程处理等需要缓存的需求
管理服务和工具组件(Enterprise Management Serivices & Utilities):系统管理和控制工具,例如备份恢复、Mysql复制、集群等
SQL接口(SQL Interface):接受用户的SQL命令,并且返回用户需要查询的结果
解析器(Parser):对SQL进行解析,判断语法是否正确
查询优化器(Optimizer):SQL语句在查询之前会使用查询优化器对查询进行优化
比如:查询一批数据,where条件中存在两个索引字段,那么索引字段能匹配的数据越少,则优先使用该索引字段
缓存(Caches & Buffers):如果查询缓存有命中的结果,就可以直接去缓存中取数据
下图是客户端是发起一次sql指令后mysql需要完成以下六个步骤,需要注意,这里的客户端并非我们常说的前端或H5端而是我们自己的服务端项目,执行一次sql操作,一般使用的持久化框架是mybatis或者hibernate。
第一步:mysql收到客户端的指令
第二步:mysql查看自己是否有缓存的数据,如果有数据直接返回,如果无数据执行后面操作
第三步:解析器对sql语法进行判断,sql执行不正确的错误消息都是从这里抛出的
第四步:查询优化器对sql优化,有可能会把sql语句重新编排,可以最大效率提升查询速度
第五步:调用对应的执行引擎去执行sql,一般常用的执行引擎有InnoDB和MyISAM,前者支持事务,后者不支持事务
第六步:mysql把查询的结果返回给客户端,同时也会保存到缓存一份,为了下次查询的时候能够从缓存获取
四、总结问题