问题
BASIC
JavaSe
消息队列
Spring框架
JUC
MySql
Base
how_select
本文用一行sql是如何执行的来解释MySql的是如何运行的
简单来讲架构Sql分为两层,Server层和存储引擎层
- server负责建立连接,分析和执行sql
- 存储引擎负责存储和提取数据
执行一行sql的运行顺序如下
- 连接器
- 涉及知识点
1. TCP三次握手
2. HTTP短链接长连接概念 - 涉及面试点
1. 如何查看 MySQL 服务被多少个客户端连接了?
2. 空闲连接会一直占用着吗?
3. MySQL 的连接数有限制吗?
4. 怎么解决长连接占用内存的问题? - 查询缓存
- 涉及知识点
1. buffer pool是什么buffer_pool - 设计面试点
1. MySQL 8.0 版本移除的是 server 层的查询缓存,并不是 Innodb 存储引擎中的 buffer pool - 解析sql
- 执行sql
- 涉及知识点
1. 预处理器
2. 优化器- explain
3. 执行器
1. 主键索引查询
2. 全表扫描
3. 索引下推
- 涉及面试点
1. 优化器就是确认使用哪个索引的阶段
2. 执行器三种查询方式 ,1,3使用索引和2不使用索引的原因,需要将整个索引部分熟悉index
执行一条 SQL 查询语句,期间发生了什么?
- 连接器:建立连接,管理连接、校验用户身份;
- 查询缓存:查询语句如果命中查询缓存则直接返回,否则继续往下执行。MySQL 8.0 已删除该模块;
- 解析 SQL,通过解析器对 SQL 查询语句进行词法分析、语法分析,然后构建语法树,方便后续模块读取表名、字段、语句类型;
- 执行 SQL:执行 SQL 共有三个阶段:
- 预处理阶段:检查表或字段是否存在;将 select * 中的 * 符号扩展为表上的所有列。
- 优化阶段:基于查询成本的考虑,选择查询成本最小的执行计划;
- 执行阶段:根据执行计划执行 SQL 查询语句,从存储引擎读取记录,返回给客户端;
[图片]
row_format
本文讲解了Mysql的数据存储结构
Mysql数据存储在什么地方
/var/lib/mysql/my_test 目录
[root@xiaolin ~]#ls /var/lib/mysql/my_test
db.opt
t_order.frm
t_order.ibd
可以看到,共有三个文件,这三个文件分别代表着:
- db.opt,用来存储当前数据库的默认字符集和字符校验规则。
- t_order.frm,t_order 的表结构会保存在这个文件。在 MySQL 中建立一张表都会生成一个.frm 文件,该文件是用来保存每个表的元数据信息的,主要包含表结构定义。
- t_order.ibd,t_order 的表数据会保存在这个文件。表数据既可以存在共享表空间文件(文件名:ibdata1)里,也可以存放在独占表空间文件(文件名:表名字.ibd)。这个行为是由参数 innodb_file_per_table 控制的,若设置了参数 innodb_file_per_table 为 1,则会将存储的数据、索引等信息单独存储在一个独占表空间,从 MySQL 5.6.6 版本开始,它的默认值就是 1 了,因此从这个版本之后,MySQL 中每一张表的数据都存放在一个独立的 .ibd 文件。
好了,现在我们知道了一张数据库表的数据是保存在「表名字.ibd」的文件里的,这个文件也称为独占表空间文件。
表空间文件的结构是怎么样的(.ibd文件)
管理方式感觉与OS的file_system类似,后续可以对比下
- 行(row)
- 数据按行为单位存放
- 页(page)
- 数据按页为单位读取
- 区(extent)
- B+树按区为单位分配叶子节点
- 段(segment)
- 索引段:存放 B + 树的非叶子节点的区的集合;
- 数据段:存放 B + 树的叶子节点的区的集合;
- 回滚段:存放的是回滚数据的区的集合,之前讲事务隔离的时候就介绍到了 MVCC 利用了回滚段实现了多版本查询数据。
InnoDB的行格式有哪些
- Redundant 是很古老的行格式了,MySQL 5.0 版本之前用的行格式,现在基本没人用了。
- 由于 Redundant 不是一种紧凑的行格式,所以 MySQL 5.0 之后引入了 Compact 行记录存储方式,Compact 是一种紧凑的行格式,设计的初衷就是为了让一个数据页中可以存放更多的行记录,从 MySQL 5.1 版本之后,行格式默认设置成 Compact。
- Dynamic 和 Compressed 两个都是紧凑的行格式,它们的行格式都和 Compact 差不多,因为都是基于 Compact 改进一点东西。从 MySQL5.7 版本之后,默认使用 Dynamic 行格式。
重点介绍 Compact 行格式,因为 Dynamic 和 Compressed 这两个行格式跟 Compact 非常像。
所以,弄懂了 Compact 行格式,之后你们在去了解其他行格式,很快也能看懂。
COMPACT 行格式长什么样?
[图片]
记录的额外信息
- 变长字段长度列表
- 扩展知识how_to_make_cpu_run_faster
- NULL 值列表
- 记录头信息
记录的真实数据 - row_id
- trx_id
- 扩展知识mvcc
- roll_pointer
varchar(n) 中 n 最大取值为多少?
单字段情况
多字段情况
行溢出后,MySQL 是怎么处理的?
Index
B+树介绍
page
本文从数据页的角度介绍了三个知识点,可作为表空间结构内容的扩展MsRequisite - 数据源本身的结构
- 数据源在B+树中的结构
- B+树种聚簇索引和二级索引的存放逻辑
why_index_chose_bpuls_tree
本文通过介绍以下的数据结构,来讨论为什么Mysql选择使用B+树 - 二分查找
- 二分查找树
- 平衡二叉树
- B树
- B+树
2000W
本文通过上面两篇文章的知识来佐证为什么MySql为什么数据量到达2000W就会影响性能,重点知识点如下 - 表空间
- 页数据结构
- 索引数据结构
索引功能介绍
index_lose
本文介绍了在哪些情况下索引会失效 - 索引存储结构长什么样?
- 对索引使用左或者左右模糊匹配
- index_issue重点讲解了索引失效在模糊查询中是如何发生了
- 对索引使用函数
- count 展开描述count函数执行流程
- 对索进行表达式计算
- 对索引隐式类型转换
- 联合索引非最左匹配
- WHERE子句中的OR
Transaction
mvcc
事务特性
事务看起来感觉简单,但是要实现事务必须要遵守 4 个特性,分别如下:
- 原子性(Atomicity):一个事务中的所有操作,要么全部完成,要么全部不完成,不会结束在中间某个环节,而且事务在执行过程中发生错误,会被回滚到事务开始前的状态,就像这个事务从来没有执行过一样,就好比买一件商品,购买成功时,则给商家付了钱,商品到手;购买失败时,则商品在商家手中,消费者的钱也没花出去。
- 一致性(Consistency):是指事务操作前和操作后,数据满足完整性约束,数据库保持一致性状态。比如,用户 A 和用户 B 在银行分别有 800 元和 600 元,总共 1400 元,用户 A 给用户 B 转账 200 元,分为两个步骤,从 A 的账户扣除 200 元和对 B 的账户增加 200 元。一致性就是要求上述步骤操作后,最后的结果是用户 A 还有 600 元,用户 B 有 800 元,总共 1400 元,而不会出现用户 A 扣除了 200 元,但用户 B 未增加的情况(该情况,用户 A 和 B 均为 600 元,总共 1200 元)。
- 隔离性(Isolation):数据库允许多个并发事务同时对其数据进行读写和修改的能力,隔离性可以防止多个事务并发执行时由于交叉执行而导致数据的不一致,因为多个事务同时使用相同的数据时,不会相互干扰,每个事务都有一个完整的数据空间,对其他并发事务是隔离的。也就是说,消费者购买商品这个事务,是不影响其他消费者购买的。
- 持久性(Durability):事务处理结束后,对数据的修改就是永久的,即便系统故障也不会丢失。
InnoDB 引擎通过什么技术来保证事务的这四个特性的呢? - 持久性是通过 redo log(重做日志)来保证的;
- 原子性是通过 undo log(回滚日志)来保证的;
- 隔离性是通过 MVCC(多版本并发控制)或锁机制来保证的;
- 一致性则是通过持久性 + 原子性 + 隔离性来保证;
并行事务引发的问题
脏读
如果一个事务「读到」了另一个「未提交事务修改过的数据」,就意味着发生了「脏读」现象。
事务中修改了数据,但是最后回滚了,别人读到了我的回滚前修改的数据,他就是脏读
[图片]
不可重复读
在一个事务内多次读取同一个数据,如果出现前后两次读到的数据不一样的情况,就意味着发生了「不可重复读」现象。
重复读的数据不一样,第一次读是正常,第二次读之前被别的事务修改了,第二次读的结果与第一次不一样
[图片]
幻读
在一个事务内多次查询某个符合查询条件的「记录数量」,如果出现前后两次查询到的记录数量不一样的情况,就意味着发生了「幻读」现象。
两个事务同时查数据数量是一样的,A事务新增了一条数据
举个栗子。
假设有 A 和 B 这两个事务同时在处理,事务 A 先开始从数据库查询账户余额大于 100 万的记录,发现共有 5 条,然后事务 B 也按相同的搜索条件也是查询出了 5 条记录。
[图片]
接下来,事务 A 插入了一条余额超过 100 万的账号,并提交了事务,此时数据库超过 100 万余额的账号个数就变为 6。
然后事务 B 再次查询账户余额大于 100 万的记录,此时查询到的记录数量有 6 条,发现和前一次读到的记录数量不一样了,就感觉发生了幻觉一样,这种现象就被称为幻读。
脏读
不可重复读
幻读
事务的隔离级别
Read View 在 MVCC 里如何工作的
可重复读是如何工作的
读提交是如何工作的
Lock
Log
BufferPool
Redis
JVM
操作系统
计算机网络
数据结构
算法
Project
Dcloud
- 分布式ID生成器Snowflake自定义wrokId + 借用sd-jdbc全局唯一ID生成器生成用户ID
- 短链码设计思路【62位与64位待验证】 + 短链码分库分表存储与读取方案 + 分库分表免数据迁移方案 + 扩容后流量倾斜方案
- 通用模型 双端数据查询(冗余双写)
- 下单接口如何防重提交(AOP + 分布式锁)
- 订单支付超时解决方案(死信队列)
Meter
HighLights
1 多级缓存OpenResty+Redis+Canal全链路 59-60-61
1 SpringBoot3.x+Haproxy+RabbitMQ高可用集群测试 73-74
1 全链路压测 82-83
1 多线程手写升级为asyncTool
2 生产环境-Kafka海量消息堆积解决方案 75
2 安全攻防案例 81
3 线上问题案例
接口防刷
通常面试官在问到项目经历的时候,都会问你在做这个项目的时候遇到了什么问题。用摸鱼时间整理一些比较优质线上问题案例或者系统性能优化的文章,希望对大家有用!
1、Java 基础、线程池、JVM
Java 应用线上问题排查思路、常用工具小结:Java 应用线上问题排查思路、常用工具小结 | Richard's Code Studio
详解一次由读写锁引起的内存泄漏 :高并发服务优化篇:详解一次由读写锁引起的内存泄漏
一次 Java 线程池误用引发的血案(OOM)和总结 - 文西(字节架构师):一次Java线程池误用引发的血案和总结 - 知乎
一次线程池引发的线上故障分析:一次线程池引发的线上故障分析
线程池运用不当的一次线上事故:线程池运用不当的一次线上事故 | HeapDump性能社区
Java 中 9 种常见的 CMS GC 问题分析与解决: Java中9种常见的CMS GC问题分析与解决 - 美团技术团队
2、MySQL 死锁、事务、编码、慢查询
MySQL死锁系列-线上死锁问题排查思路:MySQL死锁系列-线上死锁问题排查思路 - 云 社区 - 腾讯云
一个诡异的 MySQL 查询超时问题,居然隐藏着存在了两年的 BUG:一个诡异的MySQL查询超时问题,居然隐藏着存在了两年的BUG - CoderW喜欢写博客 - 博客...
MySQL 可重复读,差点就让我背上了一个 P0 事故!:MySQL 可重复读,差点就让我背上了一个 P0 事故!
慢查询引发的车祸现场,案例分析!:慢查询引发的车祸现场,案例分析!
为什么不建议在MySQL中使用UTF-8?: 为什么不建议在MySQL中使用 utf8 ?
3、Redis 高可用、高性能、分布式锁
Redis为什么变慢了?一文讲透如何排查Redis性能问题 | 万字长文:Redis为什么变慢了?一文讲透如何排查Redis性能问题 | 万字长文
如何从0到1构建一个稳定、高性能的Redis集群?(附16张图解):如何从0到1构建一个稳定、高性能的Redis集群?(附16张图解)
颠覆认知——Redis会遇到的15个「坑」,你踩过几个?:颠覆认知——Redis会遇到的15个「坑」,你踩过几个?
Redis——由分布式锁造成的重大事故:Redis——由分布式锁造成的重大事故 - 掘金
4、Kafka
一次 Kafka 消息堆积问题排查:一次 kafka 消息堆积问题排查
记一次 Kafka 重启失败问题排查:记一次 Kafka 重启失败问题排查
记一次 Kafka 集群线上扩容:记一次 Kafka 集群线上扩容
5、 Spring Boot
警惕 Spring Boot Actuator 引发的安全问题 - Kirito 的技术分享:警惕 Spring Boot Actuator 引发的安全问题
6、网络
万字长文让你掌握网络问题排查技巧!:万字长文让你掌握网络问题排查技巧!