这是我参与「第五届青训营 」伴学笔记创作活动的第 14 天
程序中对于 DB 的应用逻辑如图: 整个
DB 部分可以理解为两个部分: Server层 和 存储引擎
Server层负责建立连接、分析和执行 SQL .涉及大多数核心模块.
连接器,查询缓存、解析器、预处理器、优化器、执行器、内置函数、跨存储引擎过程
存储引擎负责数据的存储和提取。
InnoDB、MyISAM、Memory 等. 索引数据结构实现. 从 MySQL 5.5 版本开始, InnoDB 成为了 MySQL 的默认存储引擎.
Server 层
连接器
Linux 链接 MySQL:
# -h 指定 MySQL 服务得 IP 地址,如果是连接本地的 MySQL服务,可以不用这个参数;
# -u 指定用户名,管理员角色名为 root;
# -p 指定密码,如果命令行中不填写密码(为了密码安全,建议不要在命令行写密码),就需要在交互对话里面输入密码
mysql -h$ip -u$user -p
# 常用
mysql -uroot -p
MySQL采用TCP链接,先经过 TCP 三次握手
MySQL 的链接特点
- 链接有
长链接和短链接,长的少建立连接和断开连接的过程, 推荐长链接, 但是占用内存 - 最大连接数由
max_connections参数控制, 默认100 - 目前链接数可
show processlist查看,Sleep表示空闲的连接 - 最大空闲时由
wait_timeout控制,默认值是 8 小时(28880秒)
查询缓存
SQL 是查询语句(select 语句),MySQL 就会先去查询缓存( Query Cache )里查找缓存数据.
鸡肋.只要更新就删除
MySQL8.0 版本直接将查询缓存删掉了,MySQL8.0 之前的版本query_cache_type设置成DEMAND可关闭
解析 SQL
执行 SQL
- prepare 阶段,也就是预处理阶段;
- 检查 SQL 查询语句中的表或者字段是否存在;
- 将
select *中的*符号,扩展为表上的所有列;
- optimize 阶段,也就是优化阶段;
- 确定 SQL 执行方案: 根据查询成本
- execute 阶段,也就是执行阶段;
- 执行器和存储引擎交互
三种方式执行过程:
1.主键索引查询
select * from product where id = 1;
主键索引 + 等值查询
- 第一次查询调用
read_first_record函数指针指向的函数,让存储引擎定位符合条件的第一条记录。 - 记录是不存在的,就会向执行器上报记录找不到的错误,然后查询结束。如果记录是存在的,就会将记录返回给执行器;
- 执行器查询的过程是一个 while 循环,所以还会再查一次,但是这次因为不是第一次查询了,所以会调用
read_record函数指针指向的函数,永远返回 - 1,退出循环
2 . 全表扫描
select * from product where name = 'iphone';
没有用到索引
- 执行器第一次查询,会调用
read_first_record函数指针指向的函数,因为优化器选择的访问类型为 all,这个函数指针被指向为 InnoDB 引擎全扫描的接口,让存储引擎读取表中的第一条记录; Server层每从存储引擎读到一条记录就会发送给客户端,客户端是等查询语句查询完成后,才会显示出所有的记录- 执行器查询的过程是一个 while 循环,所以还会再查一次,但是这次因为不是第一次查询了,所以会调用
read_record函数,优化器选择的访问类型为 all,read_record 函数指针指向的还是 InnoDB 引擎全扫描的接口,所以接着向存储引擎层要求继续读刚才那条记录的下一条记录 - 直到存储引擎把表中的所有记录读完,退出循环,停止查询.
3. 索引下推
select * from t_user where age > 20 and reward = 100000;
联合索引:(age,reward)
- MySQL<5.6 : 每查询到一条二级索引记录,都要进行回表操作
- Server 层调用存储引擎的接口定位到 age > 20(第一个条件) 的第一条记录
- 根据二级索引的 B+ 树获取主键值,进行回表操作
- 判断该记录的 reward 是否等于 100000 (第二个条件)
- 循环,继续向存储引擎索要下一条记录
- MySQL>=5.6:索引下推
- Server 层调用存储引擎的接口定位到 age > 20(第一个条件) 的第一条记录
- 根据二级索引的 B+ 树,判断一下该索引中 reward 是否等于 100000(第二个条件):成立才回表
- 判断其他的查询条件(如果有)是否成立
- 循环,继续向存储引擎索要下一条记录
虽然 reward 列无法使用到联合索引 (最左匹配原则),但是可以索引下推