MySQL
MySQL
MySQL 面试八股知识点总结 💡
1️⃣ MySQL 底层架构
✅ 存储结构:MySQL 分为 Server 层 和 存储引擎层,其中 InnoDB 将表结构、数据和索引存储在同一个文件,而 MyISAM 则是分开存储。 ✅ 存储引擎:
- InnoDB:支持事务(ACID),行级锁,支持外键,使用 B+ 树 实现索引,崩溃后可恢复。
- MyISAM:不支持事务,仅支持表级锁,查询快但不支持数据恢复。
- Memory:数据存储在内存中,重启即丢失,适用于临时数据存储。
2️⃣ 索引(Index)🚀
✅ 索引的优缺点
- ✅ 优点:提升查询速度,减少 IO,优化排序(
ORDER BY
)和分组(GROUP BY
),确保数据唯一性。 - ❌ 缺点:增删改时需要维护索引,影响写入性能,占用额外存储空间。
✅ 索引类型
- 主键索引(Primary Key):唯一且不为空,InnoDB 默认使用 聚簇索引。
- 普通索引(Index):可以重复,可以为空。
- 唯一索引(Unique):不能重复,但可以为空。
- 联合索引(Composite Index):多个字段组成的索引,遵循 最左前缀匹配原则。
- 覆盖索引(Covering Index):查询的数据全部在索引中,不需要回表,提高查询效率。
✅ B+ 树索引 vs. Hash 索引
- B+ 树:支持范围查询(
BETWEEN
)、排序(ORDER BY
),稳定性高,InnoDB 默认使用。 - Hash:查询快但不支持范围查询,适用于 等值查询。
✅ 最左前缀匹配原则 🔍
联合索引 (
a, b, c
) 的使用顺序必须从左往右,否则索引可能失效!
SELECT * FROM table WHERE a = 1 AND b = 2; -- 走索引 ✅
SELECT * FROM table WHERE b = 2; -- 索引失效 ❌
SELECT * FROM table WHERE a = 1 AND b > 2 AND c = 3; -- c 不走索引 ❌
✅ 索引失效的情况 🚨 ❌ LIKE '%xx'
(左模糊) ❌ !=
、IS NOT NULL
❌ 在索引列上进行计算或函数操作 ❌ OR
语句中有非索引列 ❌ 优化器认为全表扫描更快(小表情况)
3️⃣ SQL 执行流程与优化
✅ SQL 执行架构: 1️⃣ 连接器(用户身份认证) 2️⃣ 查询缓存(MySQL 8.0 以后移除) 3️⃣ 解析器(SQL 语法分析) 4️⃣ 优化器(选择最优执行计划) 5️⃣ 执行器(调用存储引擎接口)
✅ 查看 SQL 执行计划
EXPLAIN SELECT * FROM table WHERE id = 1;
type
:查询类型(const
>ref
>range
>index
>ALL
)key
:实际使用的索引Extra
:索引优化情况(Using index
、Using where
等)
✅ SQL 优化技巧 🛠 🔥 避免 SELECT \*
,只查询需要的列 🔥 索引字段避免计算和函数 🔥 小表驱动大表,优化 JOIN 🔥 使用 EXPLAIN
分析执行计划,避免 ALL
全表扫描 🔥 分库分表、读写分离、引入 Redis 缓存
4️⃣ 事务(Transaction)⚡
✅ ACID 四大特性
- A(原子性):要么全部执行,要么全部回滚(
Undo Log
负责)。 - C(一致性):事务开始前后,数据必须保持一致。
- I(隔离性):并发事务之间互不影响(MVCC、锁机制)。
- D(持久性):事务提交后数据不会丢失(
Redo Log
负责)。
✅ 事务隔离级别 📌(从低到高) 1️⃣ 读未提交(Read Uncommitted)❌(可能出现脏读) 2️⃣ 读已提交(Read Committed)✅(SQL Server 默认,可能出现不可重复读) 3️⃣ 可重复读(Repeatable Read)✅(MySQL 默认,可能出现幻读) 4️⃣ 串行化(Serializable)🚫(最严格,但性能最差)
✅ 快照读 vs. 当前读
- 快照读(普通
SELECT
):不会加锁,采用 MVCC 实现。 - 当前读(
SELECT ... FOR UPDATE
):读取最新数据,并加锁防止修改。
5️⃣ MySQL 锁 🔒
✅ 表锁 vs. 行锁
- 表锁:锁整张表,影响并发性能(MyISAM 仅支持表锁)。
- 行锁:锁住符合条件的行,提高并发性能(InnoDB 采用行锁)。
✅ 共享锁(S 锁) vs. 排他锁(X 锁)
- 共享锁(S 锁):多个事务可以同时读取(
SELECT ... LOCK IN SHARE MODE
)。 - 排他锁(X 锁):只允许一个事务修改(
SELECT ... FOR UPDATE
)。
✅ 死锁 💀 及解决方案 ❌ 不同事务获取锁的顺序不同,可能会导致死锁! 💡 解决方案:
- 事务按照相同顺序获取锁
- 降级隔离级别(如 RR -> RC)
- 设置
innodb_lock_wait_timeout
超时时间
SHOW ENGINE INNODB STATUS; -- 查看死锁情况
6️⃣ MVCC 多版本并发控制 🌀
✅ MVCC 关键组成
Undo Log
:记录数据修改前的历史版本(回滚日志)。ReadView
:记录事务启动时所有活跃的事务 ID,用于确定数据版本。
✅ ReadView 版本判断规则 1️⃣ 事务 ID 小于最小活跃事务 ID ✅(可见) 2️⃣ 事务 ID 大于当前事务 ID ❌(不可见) 3️⃣ 事务 ID 在活跃事务列表中 ❌(不可见)
7️⃣ 日志系统 📝
✅ Redo Log(重做日志) 💾
- 记录 已提交的事务,保证数据持久性。
- WAL 机制(先写日志再写磁盘),提升写入效率。
✅ Undo Log(回滚日志) 🔙
- 记录 数据修改前的版本,用于事务回滚和 MVCC。
✅ Binlog(归档日志) 🔁
- 记录 所有变更,用于 数据恢复、主从复制。
8️⃣ SQL 慢查询优化 🏃♂️
✅ 如何定位慢 SQL?
- 使用
EXPLAIN
查看执行计划 SHOW PROCESSLIST
监控执行中的 SQLSHOW ENGINE INNODB STATUS
查看死锁slow_query_log
慢查询日志
✅ 深度分页优化(LIMIT 100000, 10) ❌ LIMIT M, N
先扫描 M 条记录再丢弃,导致性能低下。 ✅ 方案:使用 主键索引优化 或 ES 进行分页查询。
🎯 总结:熟练掌握 MySQL 事务、索引优化、SQL 调优、锁机制,是面试的核心竞争力! 🚀