
目录
[Day 1:SQL基础](#Day 1:SQL基础)
[1. 什么是SQL?(Structured Query Language)](#1. 什么是SQL?(Structured Query Language))
[2. SQL语句有哪些分类?](#2. SQL语句有哪些分类?)
[3. 增删改查(CRUD)](#3. 增删改查(CRUD))
[4. SELECT查询执行顺序(重点)](#4. SELECT查询执行顺序(重点))
[5. Where和Having区别(面试常问)](#5. Where和Having区别(面试常问))
[6. GROUP BY是什么?⭐⭐⭐](#6. GROUP BY是什么?⭐⭐⭐)
[7. JOIN是什么?⭐⭐⭐⭐](#7. JOIN是什么?⭐⭐⭐⭐)
[Day 2:MySQL索引 ⭐](#Day 2:MySQL索引 ⭐)
[1. 什么是索引?(必背)](#1. 什么是索引?(必背))
[2. 为什么需要索引?](#2. 为什么需要索引?)
[3. 索引的底层结构是什么?⭐⭐⭐⭐](#3. 索引的底层结构是什么?⭐⭐⭐⭐)
[4. 为什么不用二叉树?为什么不用Hash索引?⭐⭐⭐⭐](#4. 为什么不用二叉树?为什么不用Hash索引?⭐⭐⭐⭐)
[5. B+Tree是什么?⭐⭐⭐⭐⭐](#5. B+Tree是什么?⭐⭐⭐⭐⭐)
[6. 索引的优缺点 ⭐⭐⭐⭐](#6. 索引的优缺点 ⭐⭐⭐⭐)
[7. 什么字段适合建立索引?⭐⭐⭐⭐](#7. 什么字段适合建立索引?⭐⭐⭐⭐)
9、那B+Tree和B树相比,有什么区别?为什么数据库更喜欢B+Tree?
[Day 3:MySQL 索引进阶 🔥](#Day 3:MySQL 索引进阶 🔥)
[1. 什么是聚簇索引?🔥🔥🔥](#1. 什么是聚簇索引?🔥🔥🔥)
[2. 什么是二级索引?🔥🔥🔥](#2. 什么是二级索引?🔥🔥🔥)
[3. 什么是回表?什么是覆盖索引?🔥🔥🔥(高频)](#3. 什么是回表?什么是覆盖索引?🔥🔥🔥(高频))
[4. 什么是联合索引?什么是最左匹配原则?🔥🔥🔥🔥](#4. 什么是联合索引?什么是最左匹配原则?🔥🔥🔥🔥)
[5. 哪些情况可能导致索引失效?🔥🔥🔥🔥(高频)](#5. 哪些情况可能导致索引失效?🔥🔥🔥🔥(高频))
[6. 为什么不建议 select * ?🔥🔥](#6. 为什么不建议 select * ?🔥🔥)
7、为什么①通常可以正常利用索引,而②对索引列使用函数后可能无法正常利用这个索引?
[Day 4:MySQL 事务篇 🧩](#Day 4:MySQL 事务篇 🧩)
[1. 什么是事务?💎为什么需要事务?🔷](#1. 什么是事务?💎为什么需要事务?🔷)
[3. 事务MySQL中怎么使用?🔷](#3. 事务MySQL中怎么使用?🔷)
[4. 什么是 ACID?💎💎](#4. 什么是 ACID?💎💎)
[5. 并发事务会出现什么问题?💎💎](#5. 并发事务会出现什么问题?💎💎)
[① 脏读 💎](#① 脏读 💎)
[②不可重复读 💎](#②不可重复读 💎)
[③幻读 💎](#③幻读 💎)
[6. MySQL事务隔离级别 💎💎](#6. MySQL事务隔离级别 💎💎)
[7. MySQL InnoDB 默认隔离级别 💎💎](#7. MySQL InnoDB 默认隔离级别 💎💎)
[8. 四种隔离级别解决什么问题?💎](#8. 四种隔离级别解决什么问题?💎)
[Day 5:MVCC + MySQL 锁 🛡️](#Day 5:MVCC + MySQL 锁 🛡️)
[1、什么是 MVCC?🔥🔥🔥](#1、什么是 MVCC?🔥🔥🔥)
[2 、为什么需要 MVCC?🔥🔥🔥](#2 、为什么需要 MVCC?🔥🔥🔥)
[3、undo log的两大作用:](#3、undo log的两大作用:)
[4、Read View](#4、Read View)
[🍉为什么 InnoDB 的 Repeatable Read(可重复读)能够解决不可重复读问题?请从undo log、MVCC、版本链和 Read View 的角度解释。](#🍉为什么 InnoDB 的 Repeatable Read(可重复读)能够解决不可重复读问题?请从undo log、MVCC、版本链和 Read View 的角度解释。)
[表锁 vs 行锁](#表锁 vs 行锁)
[记录锁(Record Lock)vs 间隙锁(Gap Lock)](#记录锁(Record Lock)vs 间隙锁(Gap Lock))
[为啥(临键锁) Next-Key Lock 能帮助防止幻读?🔥🔥🔥🔥](#为啥(临键锁) Next-Key Lock 能帮助防止幻读?🔥🔥🔥🔥)
[7、InnoDB 在 RR 隔离级别下,是怎么处理幻读问题的?](#7、InnoDB 在 RR 隔离级别下,是怎么处理幻读问题的?)
[8、为什么说 InnoDB 的查询条件如果没有合适的索引,可能导致"锁范围扩大",甚至表现得像锁表?](#8、为什么说 InnoDB 的查询条件如果没有合适的索引,可能导致“锁范围扩大”,甚至表现得像锁表?)
[🍉快照读 && 当前读](#🍉快照读 && 当前读)
[9、为什么 SELECT ... FOR UPDATE 不能像普通 SELECT 一样只读取历史快照,而要读取当前最新的数据并加锁?](#9、为什么 SELECT ... FOR UPDATE 不能像普通 SELECT 一样只读取历史快照,而要读取当前最新的数据并加锁?)
[🍉事务 A COMMIT 之后,事务 B 会发生什么?](#🍉事务 A COMMIT 之后,事务 B 会发生什么?)
[🍉如果事务 A 还是持有 X Lock,但事务 B 执行select](#🍉如果事务 A 还是持有 X Lock,但事务 B 执行select)
[事务 B 会不会被阻塞?为什么?](#事务 B 会不会被阻塞?为什么?)
[Day6:SQL 优化与 EXPLAIN 🔥🔥🔥🔥](#Day6:SQL 优化与 EXPLAIN 🔥🔥🔥🔥)
[第一题 🔥🔥🔥:什么是慢 SQL?](#第一题 🔥🔥🔥:什么是慢 SQL?)
[第二题 🔥🔥🔥🔥:EXPLAIN 是干什么的?](#第二题 🔥🔥🔥🔥:EXPLAIN 是干什么的?)
[第三题 🔥🔥🔥🔥:](#第三题 🔥🔥🔥🔥:)
[为什么不能看到 key != NULL、SQL 使用了索引,就直接判断"这条 SQL 性能很好"?](#为什么不能看到 key != NULL、SQL 使用了索引,就直接判断“这条 SQL 性能很好”?)
[为什么 Extra = Using index 通常是一个比较好的信号?](#为什么 Extra = Using index 通常是一个比较好的信号?)
[Day7:InnoDB 底层 + MySQL 日志体系](#Day7:InnoDB 底层 + MySQL 日志体系)
[1、什么是 Buffer Pool?InnoDB 为什么需要 Buffer Pool?](#1、什么是 Buffer Pool?InnoDB 为什么需要 Buffer Pool?)
[2、是不是每执行一次 UPDATE,MySQL 都要立刻把修改后的数据写回磁盘?](#2、是不是每执行一次 UPDATE,MySQL 都要立刻把修改后的数据写回磁盘?)
[3、既然有了 redo log,为什么还需要 binlog?redo log 和 binlog 有什么区别?](#3、既然有了 redo log,为什么还需要 binlog?redo log 和 binlog 有什么区别?)
[4、为什么 MySQL 需要两阶段提交?](#4、为什么 MySQL 需要两阶段提交?)
[5、redo log 为什么叫"循环写"? binlog叫"追加写"?](#5、redo log 为什么叫“循环写”? binlog叫“追加写”?)
Day 1:SQL基础
1. 什么是SQL?(Structured Query Language)
回答:
是一种用于 操作关系型数据库的语言。
主要用于对数据库中的数据进行:
定义、操作、查询、控制。
比如:
MySQL、Oracle(/ˈɔːrəkəl/)、PostgreSQL(波斯格瑞) 等关系型数据库都支持SQL
2. SQL语句有哪些分类?
MySQL中常见分为:
① DDL(Data Definition Language)
是 数据定义语言,主要用来 定义数据库对象结构
比如数据库、表、字段等
常见操作包括 create、alter、drop、truncate。
create用于创建数据库对象,比如创建表
alter用于修改数据库对象结构,如增加字段、修改字段类型、删除字段等。
🍉区分:
drop:删除整个表对象,表结构和数据都会被删除。
truncate:清空表中的所有数据,但是保留表的结构和字段,之后仍然可以继续使用这个表。
② DML(Data Manipulation Language)
是 数据操作语言,主要用于操作表中的数据
包括:insert、update、delete
🍉为什么update/delete一定要加where?
update和delete加where条件是为了指定操作的数据范围。如果不加where条件,会默认操作整张表的数据,可能导致大量数据被错误修改或删除
③ DQL(Data Query Language)
是 数据查询语言,最常用的命令是select
用于 查询指定字段、筛选数据以及 进行排序、分组统计等操作
④ DCL(Data Control Language)
是 数据控制语言。主要用于管理数据库用户的权限,
常见命令有 grant用于授权,revoke用于撤销权限
3. 增删改查(CRUD)
| #### 英文 | #### 中文 | #### SQL |
|---|---|---|
| #### Create | #### 创建 | #### INSERT |
| #### Read | #### 读取 | #### SELECT |
| #### Update | #### 更新 | #### UPDATE |
| #### Delete | #### 删除 | #### DELETE |
🍉什么是CRUD?
CRUD是数据库中最基本的数据操作,包括创建、查询、修改、删除,
对应SQL中的 insert、select、update、delete。
4. SELECT查询执行顺序(重点)
先找表(from),再过滤(where),再分组(group by),
再过滤组(having),再选字段(select),
再排序(order by),再分页(limit)
java
select name, count(*)
-- 选择最终要返回的字段,并使用count(*)统计数量
from user
-- 从user表中获取数据(确定数据来源)
where age > 18
-- 过滤原始数据,只保留年龄大于18的数据
group by name
-- 根据name字段进行分组
having count(*) > 5
-- 对分组后的结果进行过滤,只保留数量大于5的组
order by count(*) desc
-- 按统计数量进行降序排序(从大到小)
limit 10;
-- 最后只返回10条数据(分页)
5. Where和Having区别(面试常问)
where 和 having都是用于 过滤数据,区别在于
where过滤的是原始数据,在group by之前执行
having过滤的是分组后的结果,在group by之后执行。
where不能使用聚合函数,而having可以结合count、max、min等聚合函数。
6. GROUP BY是什么?⭐⭐⭐
对查询结果进行分组统计
例如:
统计每个城市用户数量。
user表:
| name | city |
|---|---|
| 张三 | 上海 |
| 李四 | 上海 |
| 王五 | 北京 |
分组结果:
| city | count |
|---|---|
| 上海 | 2 |
| 北京 | 1 |
GROUP BY通常和聚合函数一起使用,例如:
count()、sum()、avg()、max()、min()
7. JOIN是什么?⭐⭐⭐⭐
用于多张表之间进行关联查询。常见JOIN类型有
inner join(内连接)
只返回两个表都有的数据
left join(左连接)
返回左表全部数据,以及右表匹配数据
Day 2:MySQL索引 ⭐
1. 什么是索引?(必背)
索引是一种帮助数据库快速查询数据的数据结构,主要用于提高数据库的查询效率,减少全表扫描
2. 为什么需要索引?
当数据量较大时,如果没有索引,数据库需要进行全表扫描,查询效率较低;
使用索引可以快速定位数据,提高查询效率。
3. 索引的底层结构是什么?⭐⭐⭐⭐
MySQL InnoDB存储引擎默认使用B+Tree作为索引结构。
🍉为什么使用B+Tree?
查询效率稳定、支持范围查询、树高度较低
4. 为什么不用二叉树?为什么不用Hash索引?⭐⭐⭐⭐
普通二叉树
如果使用普通二叉树、数据在有序的情况下、可能退化成链表。
时间复杂度变成O(n)、效率下降
Hash索引
优点:等值查询快。
缺点:
①不支持范围查询
②不支持排序
5. B+Tree是什么?⭐⭐⭐⭐⭐
B+Tree是一种多叉平衡搜索树,MySQL利用它来组织索引数据。
特点:
① 多叉:
一个节点可以存储多个关键字、因此树的高度比较低,可以减少磁盘I/O次数
② 所有数据存储在叶子节点
③ 叶子节点通过链表连接:方便范围查询
6. 索引的优缺点 ⭐⭐⭐⭐
优点:
① 提高查询效率,减少扫描数据。
② 提高排序效率
缺点:
① 占用额外空间,因为索引本身需要存储。
② 降低 增删改 效率,因为修改数据时,需要同时维护索引
7. 什么字段适合建立索引?⭐⭐⭐⭐
① 经常作为查询条件
② 经常排序
③ 经常用于JOIN查询
🍉什么字段不适合?
① 区分度比较低、重复值很多的字段
② 经常修改的字段
因为维护成本高。
8、为什么B+Tree特别适合范围查询?
做范围查询时,可以先通过B+Tree快速定位到范围起点,比如100,然后从这个叶子节点开始,沿着链表顺序向后扫描,直到200为止,所以范围查询效率比较高
9、那B+Tree和B树相比,有什么区别?为什么数据库更喜欢B+Tree?
B树的非叶子节点也可以存储数据;
而B+树的数据集中在叶子节点,非叶子节点主要用于索引。
这样B+树的非叶子节点可以容纳更多索引项,使树的高度更低;
同时B+树的叶子节点有序连接,因此更适合范围查询
Day 3:MySQL 索引进阶 🔥
1. 什么是聚簇索引?🔥🔥🔥
①聚簇索引是数据和索引存储在一起的索引。
②比如在InnoDB中,聚簇索引的叶子节点 存储完整的数据行
通常主键索引就是聚簇索引
2. 什么是二级索引?🔥🔥🔥
又叫:
非聚簇索引 / Secondary Index
二级索引的叶子节点一般不存完整数据行,而是存 索引字段 + 主键值。
3. 什么是回表?什么是覆盖索引?🔥🔥🔥(高频)
回表是指通过二级索引查询时,其中没有查询所需要的全部字段,
就需要先通过二级索引找到主键值,再根据主键到聚簇索引中查询完整数据,
这个过程叫回表。
查询所需要的字段全部能够从索引中直接获得,
不需要再回表查询,这种情况叫覆盖索引
4. 什么是联合索引?什么是最左匹配原则?🔥🔥🔥🔥
联合索引:同时基于多个字段建立的索引
查询条件要尽量从联合索引 最左边的字段开始匹配。
遇到范围查询后,范围字段可以使用索引,但其后的字段通常不能继续用于缩小索引扫描范围
5. 哪些情况可能导致索引失效?🔥🔥🔥🔥(高频)
① 违反联合索引最左匹配
② 对索引列进行函数操作
③ 对索引列进行计算
④ LIKE 以
%开头
6. 为什么不建议 select * ?🔥🔥
①可能增加不必要的数据读取
②并可能导致无法利用覆盖索引
③增加回表查询成本
7、为什么①通常可以正常利用索引,而②对索引列使用函数后可能无法正常利用这个索引?
java
① where name = 'Felix';
② where lower(name) = 'felix';
索引存的是原始值的有序结构,但查询条件用的是计算后的值,
因此数据库可能无法直接根据原索引定位数据
后
%:开头确定,知道从哪找。前
%:开头不确定,不知道从哪找。
java
where name = 'Felix'
and age = 20
and city > '上海';
最左匹配:
①中间缺字段会断;
②遇到范围查询,范围列能用,但后面的列不能继续用于缩小联合索引的扫描范围。
Day 4:MySQL 事务篇 🧩
1. 什么是事务?💎为什么需要事务?🔷
事务是一组数据库操作的集合,这些操作要么全部成功,要么全部失败,用来保证数据的 一致性和可靠性
(防止执行过程中出现异常导致数据处于错误状态)
3. 事务MySQL中怎么使用?🔷
sql
start transaction
开始事务
commit
提交事务
rollback
回滚事务
4. 什么是 ACID?💎💎
事务有四大特性:
原子性:Atomicity
一个事务中的操作要么全部成功,要么全部失败。
一致性:Consistency
事务执行前后,数据都应该保持合法、一致的状态(总金额)
隔离性:Isolation
多个事务并发执行时,事务之间应该尽量互不干扰
持久性:Durability
事务一旦commit提交成功,修改的数据就应该被持久保存。
5. 并发事务会出现什么问题?💎💎
① 脏读 💎
一个事务读到了另一个事务还没有提交的数据。
②不可重复读 💎
同一个事务中,对同一条数据读取两次,结果不一样。
③幻读 💎
在同一个事务中,使用相同的查询条件进行多次查询,得到的记录集合不一致。
6. MySQL事务隔离级别 💎💎
| #### 隔离级别 | #### 中文 | #### 简单理解 |
|---|---|---|
| #### Read Uncommitted | #### 读未提交 | #### 别人没提交我也能读 |
| #### Read Committed | #### 读已提交 | #### 只能读别人已提交的数据 |
| #### Repeatable Read | #### 可重复读 | #### 同一事务中重复读取保持一致 |
| #### Serializable | #### 串行化 | #### 事务高度串行执行 |
7. MySQL InnoDB 默认隔离级别 💎💎
InnoDB 默认事务隔离级别是 Repeatable Read(RR,可重复读)
8. 四种隔离级别解决什么问题?💎
| #### 隔离级别 | #### 脏读 | #### 不可重复读 | #### 幻读 |
|---|---|---|---|
| #### Read Uncommitted | #### ❌ #### 可能 | #### ❌ #### 可能 | #### ❌ #### 可能 |
| #### Read Committed | #### ✅ #### 解决 | #### ❌ #### 可能 | #### ❌ #### 可能 |
| #### Repeatable Read | #### ✅ #### 解决 | #### ✅ #### 解决 | #### ⚠️标准定义下仍需关注幻读;InnoDB有额外机制处理许多幻读场景 |
| #### Serializable | #### ✅ | #### ✅ | #### ✅ |
Day 5:MVCC + MySQL 锁 🛡️
1、什么是 MVCC?🔥🔥🔥
Multi-Version Concurrency Control,多版本并发控制。
MVCC是一种并发控制机制,
一条数据维护多个版本,让不同事务读取适合自己的版本,提高并发性能
2 、为什么需要 MVCC?🔥🔥🔥
你改你的新版本,我读我的旧版本,大家尽量别互相等。
3、undo log的两大作用:
undo log
①是回滚日志,主要用于事务回滚。
②帮助构建历史版本链。
MVCC 可以基于这些版本链,让不同事务读取自己想要的版本。
4、Read View
Read View 相当于一套可见性规则,用来判断版本链中的哪些数据版本能被当前事务读取
🍉为什么 InnoDB 的 Repeatable Read(可重复读)能够解决不可重复读问题?请从undo log、MVCC、版本链和 Read View 的角度解释。
undo log 记录数据修改前的相关信息,帮助构建版本链。Read View 是一套可见性规则,用于判断版本链中哪些数据能被当前事务读取。
RR 下同一个事务会保持一致的Read View,所以即使其他事务修改并提交了数据,我还是可以读取之前对我可见的版本,从而实现可重复读。
5、什么是快照读和当前读?🔥🔥🔥
快照读读取的是 MVCC 中对当前事务可见的数据版本;
当前读读取的是当前最新的数据,通常需要加锁。
6、什么是共享锁和排他锁?
共享锁(Shared Lock,S锁)
允许多个事务同时读取同一份数据,但会限制其他事务对该数据进行修改
排他锁(Exclusive Lock,X锁)
加了X锁后,其他事务不能再获取其它S锁或X锁,需要等待当前事务释放锁。
表锁 vs 行锁
表锁是锁住整张表,锁粒度比较大,并发性能相对低;
行锁是锁定具体的 索引记录,锁粒度更小,并发性能更好。
(锁粒度 = 锁的范围大小)
记录锁(Record Lock)vs 间隙锁(Gap Lock)
Record Lock:锁住某一条具体的索引记录。
Gap Lock: 锁住两条索引记录之间的间隙
为啥(临键锁) Next-Key Lock 能帮助防止幻读?🔥🔥🔥🔥
Next-Key Lock 是 Record Lock 和 Gap Lock 的结合。
它既可以锁住已有的索引记录,又可以锁住记录之间的间隙,从而阻止其他事务在相应范围内插入新的记录,因此可以帮助防止幻读。
7、InnoDB 在 RR 隔离级别下,是怎么处理幻读问题的?
InnoDB 在 RR 隔离级别下主要通过 MVCC 和 锁机制 处理幻读场景。
①对于普通快照读,通过 MVCC、版本链和 Read View 保持 数据的一致
②对于当前读,则通过 Gap Lock、Next-Key Lock 等锁机制锁住相应的索引范围和间隙,防止其他事务插入新的记录,从而处理幻读问题。
8、为什么说 InnoDB 的查询条件如果没有合适的索引,可能导致"锁范围扩大",甚至表现得像锁表?
如果查询条件没有合适的索引,可能需要进行全表扫描,并锁住大量扫描到的索引记录,导致锁范围扩大,影响并发性能。
🍉什么情况下行锁可能退化成类似"锁表"的效果?
查询/更新条件中的字段没有合适的索引。
🍉快照读 && 当前读
普通 SELECT 一般属于快照读,通过 MVCC 和 Read View 读取当前事务可见的数据版本;
SELECT ... FOR UPDATE 属于当前读,会读取最新的数据版本,并对相关记录加锁。
9、为什么 SELECT ... FOR UPDATE 不能像普通 SELECT 一样只读取历史快照,而要读取当前最新的数据并加锁?
因为
SELECT ... FOR UPDATE通常是为了后续修改数据,所以需要读取当前最新的数据,并对相关记录加锁,防止其他事务同时进行冲突修改。
🍉事务 A COMMIT 之后,事务 B 会发生什么?
COMMIT 不仅提交事务的数据修改,还会释放该事务持有的锁。
🍉如果事务 A 还是持有 X Lock,但事务 B 执行select
事务 B 会不会被阻塞?为什么?
事务 B 通常不会被阻塞,因为普通
SELECT属于快照读,它通过 MVCC,根据 Read View 的可见性规则,从版本链中读取当前事务可见的数据版本。
Day6:SQL 优化与 EXPLAIN 🔥🔥🔥🔥
第一题 🔥🔥🔥:什么是慢 SQL?
慢 SQL(执行时间较长、执行效率较低的 SQL) → 慢查询日志定位具体SQL → EXPLAIN 分析执行计划 → 重点看四个字段 → 针对性优化
(比如建立或调整合适的索引、优化联合索引、避免索引失效、减少
SELECT *、优化深分页等。优化之后再重新通过 EXPLAIN 和实际执行情况验证优化效果。)
第二题 🔥🔥🔥🔥:EXPLAIN 是干什么的?
MySQL 打算怎么执行这条 SQL?
type → 怎么找数据的?
key → 本次执行实际使用的索引
rows → 预计 扫描的行数
Extra → 还有什么额外执行信息?
第三题 🔥🔥🔥🔥:
type = ALL:扫描整张表
type = index:MySQL 需要扫描整棵索引
type = range:只扫描符合条件的一段索引范围,而不是扫描整棵索引
type = ref:通过普通索引进行等值匹配,可能匹配到多条记录
type = const:通过主键索引或唯一索引进行等值查询,并且最多只匹配一条记录
🔥 一般至少希望查询达到 range 级别,最好能达到 ref;
出现 index、ALL 时需要重点关注,但不是看到 ALL 就一定有问题。
为什么不能看到 key != NULL、SQL 使用了索引,就直接判断"这条 SQL 性能很好"?
结合rows
为什么 Extra = Using index 通常是一个比较好的信号?
Using index → 使用了覆盖索引 ⭐
Using where → 还需要根据 WHERE 条件进行过滤
Using filesort→ 需要额外进行排序 🚨
Using temporary→ 使用了临时表 🚨
第四题:SQL优化---深分页
sql
SELECT *
FROM orders
ORDER BY id
LIMIT 1000000, 10;
LIMIT offset, size在 offset 很大时会产生深分页问题,因为数据库需要扫描并丢弃前面大量数据,最终只返回少量记录,造成不必要的扫描开销。
优化后:
sql
SELECT *
FROM orders
WHERE id > 1000000 !!!
ORDER BY id
LIMIT 10;
Day7:InnoDB 底层 + MySQL 日志体系
1、什么是 Buffer Pool?InnoDB 为什么需要 Buffer Pool?
Buffer Pool 是 InnoDB 在 内存 中的缓冲区域,
用于缓存数据页等内容,减少磁盘 I/O,提高数据库性能。
2、是不是每执行一次 UPDATE,MySQL 都要立刻把修改后的数据写回磁盘?
InnoDB 更新数据时,通常先修改 Buffer Pool,并记录 redo log,之后再把脏页刷回磁盘,而不是每次 UPDATE 都立即写磁盘。
① 脏页
这种已经被修改、但还没有刷回磁盘的数据页,叫脏页。
② redo log
记录"这次修改做了什么",用于在数据库异常恢复时重新执行这些修改。
3、既然有了 redo log,为什么还需要 binlog?redo log 和 binlog 有什么区别?
redo log 主要用于 InnoDB 的崩溃恢复;
binlog 主要用于 主从复制 和 数据恢复
redo log 是 InnoDB 的日志,而 binlog 是 MySQL Server 层面的日志,
因此 MySQL 需要同时维护这两套日志。
4、为什么 MySQL 需要两阶段提交?
MySQL 使用两阶段提交,是为了保证 redo log 和 binlog 的一致性,避免出现一个日志已经记录事务提交、另一个日志却没有记录的情况。
5、redo log 为什么叫"循环写"? binlog叫"追加写"?
redo log 空间有限,通过循环写实现空间复用。
而 binlog 需要记录数据库的历史变更,用于主从复制和数据恢复,因此通常采用追加写的方式保存日志。
6、一个update的背后流程图
sql
UPDATE
↓
┌──────────────┐
│ Buffer Pool │
│ 修改数据页 │
└──────┬───────┘
↓
脏页
│
┌──────┴──────┐
↓ ↓
redo log binlog
崩溃恢复 复制/恢复
↘ ↙
两阶段提交
保证日志一致
↓
后续脏页刷盘