鸟瞰MySQL全貌
select * from T where ID = 10;
MySQL基本架构示意图:
MySQL
- Server层:涵盖 MySQL 的大多数核心服务功能,以及所有的内置函数(如日期、时间、数学和加密函数等),所有跨存储引擎的功能都在这一层实现,比如存储过程、触发器、视图等
- 连接器
- 查询缓冲
- 分析器
- 优化器
- 执行器
- 存储引擎层:负责数据的存储和提取,其架构模式是插件式的。5.5.5版本及以后InnoDB成为默认的存储引擎
连接器
连接器负责跟客户端建立连接、获取权限(根据账号密码判断权限)、维持和管理连接。
mysql -h$ip -P$port -u$user -p
-
ip: ip地址
-
port: 端口号
-
user:用户
-p 后可接密码,但不建议这么做,因为可以用history查看终端的所有密码,可能会导致密码的泄露
这里会完成一个经典的TCP握手的过程
之后会认证身份
- 如果认证不通过,则收到一个"Access denied for user"的错误
- 如果认证通过,则通过权限表查询所拥有的权限
**注意:**这意味着如果一个用户成功建立连接后,修改了用户的权限,但不会影响该连接的权限,只有重新建立连接的时候才会使用新的权限设置
至此,连接已完成。
如果没有后续的操作,这个连接处于空闲状态,使用show processlist命令查看。
如果客户端太长时间没有动静,连接器会自动断开连接,连接器通过wait_timeout参数控制时间,默认为8小时
长连接
长连接是指连接成功后,如果客户端持续有请求,则一直使用同一个连接。
短链接
短连接则是指每次执行完很少的几次查询就断开连接,下次查询再重新建立一个。
由于建立连接的过程通常是比较复杂的,所以我们需要尽量使用长连接。
问题:MySQL在都使用长连接时可能出现mysql占用内存涨的特别快的情况
原因:使用长连接,MySQL在执行过程中临时使用的内存管理在连接对象中,而这些资源需要在连接断开时才会被释放。
后果:进程被系统杀掉(OOM),MySQL异常重启
解决办法:
- 定期断开连接,并且当执行一个占用内存大的查询后,断开连接。
- MySQL5.7+,每次执行一个占用内存大的操作后,执行mysql_reset_connection重新初始化连接资源,这个过程不需要重新连接和重新做权限验证,只是把连接恢复到刚刚创建完成时的状态。
查询缓存
依据MySQL基本架构图可知,当连接器完成连接后,执行select语句就先从查询缓存中查找之前是否缓存了这个key
key是查询语句
value是查询结果
- 如果能找到,则直接返回结果
- 如果找不到,则继续下一阶段,完成查询后,将查询结果存入查询缓存中。
不建议使用查询缓存
原因:查询缓存失效非常频繁,只要对表进行了更新,查询缓存就会被清空
MySQL提供了“按需使用”的方式:将参数 query_cache_type 设置成 DEMAND,用 SQL_CACHE 显式指定。
select SQL_CACHE * from T where ID=10;
注意:MySQL8.0将查询缓存整块删除了。
分析器
MySQL需要知道你要做什么,分析器的工作就是解析SQL语句,分为词法分析和语法分析
-
词法分析
MySQL需要将输入的SQL语句识别出每一部分字符串代表什么含义,比如:select代表这是一个查询语句,T代表表名等,检查语句中的关键词,表,字段是否存在
-
语法分析
根据词法分析的结果,语法分析器会根据语法规则判断是否满足要求
优化器
优化器是在表里面有多个索引的时候,决定使用哪个索引;或者在一个语句有多表关联(join)的时候,决定各个表的连接顺序
执行器
MySQL通过分析器知道了要做什么,通过优化器知道了怎么做,然后进入执行器执行
首先在执行器中需要判断用户是否有权限操作该表
- 如果没有,则返回没有权限的错误
- 如果有权限,则打开表进行执行,调用引擎提供的接口
连接器是账号权限校验 分析器是库权限验证 执行器是语句在表中权限验证
存储引擎一般按页读取到内存中,然后执行器调用存储引擎接口按行扫描。