MySQL 相关知识及面试问题汇总

一、前言

对以往接触到的 MYSQL 相关技术及面试中有可能遇到的问题进行汇总整理(不定期更新),方便未来查阅复习。

二、MySQL 简介

MySQL 是目前世界上最流行的开源关系型数据库管理系统(RDBMS),基于 client-server 架构,使用 SQL 进行数据管理。由于其高性能、高可靠性、易用性及开源免费的特性,被广泛用于互联网应用(如 Facebook,Twitter,淘宝等)作为数据存储层。

三、相关知识

3.1 事务隔离级别

事务的四大特性 ACID(原子性、一致性、隔离性、持久性),为了解决并发事务带来的问题(脏读、不可重复、幻读),SQL 标准定义了四种隔离级别。

|-----------------------|------------------------------|----|-------|-----------------|
| 隔离级别 | 描述 | 脏读 | 不可重复读 | 幻读 |
| Read Uncommitted 读未提交 | 一个事务可以读取另一个未提交事务的数据 | ✅ | ✅ | ✅ |
| Read Committed 读已提交 | 一个事务只能读取已经提交的事务的数据(Oracle默认) | ❌ | ✅ | ✅ |
| Repeatable Read 可重复读 | 同一事务中多次读取的结果一致(InnoDB 默认) | ❌ | ❌ | ✅ InnoDB多数场景可避免 |
| Serializable 串行化 | 强制事务串行执行 | ❌ | ❌ | ❌ |

3.2 MVCC(多版本并发控制)原理

MVCC 是 InnoDB 实现 Read Committed 和 Repeatable Read 隔离级别的核心机制,它通过保存数据在某个时间点的快照,使得读操作不需要加锁,大大提高了并发性能。

核心组成:

  • 隐藏字段:InnoDB 会给每行数据添加三个隐藏字段:
    • DB_TRX_ID:最近修改(或插入)该行数据的事务 ID;
    • DB_ROLL_PTR:回滚指针,指向 Undo Log 中上一个版本的记录;
    • DB_ROW_ID:隐藏的主键(如果表没有主键)。
  • Undo Log(回滚日志):当事务修改数据时,MySQL 会将旧数据写入 Undo Log,通过回滚指针,形成一条版本链。
  • Read View(读视图):事务进行快照读时产生的读视图,它决定了事务能看到版本链中的哪条数据。
    • m_ids:生成 Read View 时,当前系统中活跃(未提交)的事务 ID 列表;
    • min_trx_id:活跃事务中最小的 ID;
    • max_trx_id:系统应该分配给下一个事务的 ID。

RC 与 RR 在 MVCC 上的区别:

  • Read Committed:在每一次进行普通 Select 操作前都会生成一个新的 Read View,所以它能读到别的事务刚刚提交的数据。
  • Repeatable Read:只在事务开启后的第一次 Select 操作前生成 Read View,之后复用这个 Read View,所以即使别的事务提交了修改,当前事务看到的依然是旧版本,从而实现了"可重复读"。
3.3 MySQL 的"三大日志"

MySQL 的数据安全和主从复制依赖于日志系统,最重要的是 Redo Log、Undo Log 和 Binlog。

  1. Redo Log(重做日志)- 物理日志
  • 作用:保证事务的持久性(Durability),实现 Crash-safe 能力。
  • 原理:WAL(Write-Ahead Logging)技术,先写日志,再写磁盘。
  • 特点:
    • InnoDB 存储引擎层特有的。
    • 记录的是"在某个数据页上做了什么修改"。
    • 是循环写的,固定大小,写满后需要擦除旧记录(Checkpoint)。
  1. Undo Log(回滚日志)- 逻辑日志
  • 作用:保证事务的原子性(Atomicity)和实现 MVCC。
  • 原理:记录数据的逻辑变化。例如执行一条 INSERT,Undo Log 就记录一条 DELETE;执行 UPDATE,就记录相反的 UPDATE。
  • 场景:事务回滚时,通过 Undo Log 将数据恢复到修改前的样子。
  1. Binlog(归档/二进制日志)- 逻辑日志
  • 作用:用于主从复制和数据恢复(如误删库后的恢复)。
  • 特点:
    • 是 MySQL Server 层实现的,所有引擎都可以使用。
    • 是追加写的,不会覆盖旧日志。
    • 记录的是 SQL 语句的原始逻辑(如 Statement 格式)或行数据的变更(Row 格式)。

四、面试问题

4.1 为什么 InnoDB 选择 B+ 树作为索引结构,而不是 B 树或 Hash
  • Hash 查询效率极高,但不支持范围查询和排序;
  • B 树的每个节点都存储数据,B+ 树只有叶子结点存储数据,非叶子结点只存索引
    • 非叶子结点能容纳更多索引,磁盘 I/O 次数更少;
    • B+ 树的叶子结点通过双向链表连接,范围查询时只需遍历链表,而 B 树需要进行中序遍历。
4.2 聚簇索引和非聚簇索引
  • 聚簇索引
    • 数据行和相邻的键值紧凑地存储在一起;
    • InnoDB 的主键索引就是聚簇索引,叶子结点存储的是整行数据;
    • 一张表只能有一个聚簇索引。
  • 非聚簇索引
    • 叶子节点存储的是索引列的值和主键 ID;
    • 回表:如果通过二级索引查询非索引列的数据,需要先拿到主键 ID,再去聚簇索引(主键索引)中查找完整的行数据,这个过程叫回表。
4.3 最左前缀原则

假设有一个联合索引(a, b, c),查询条件必须从最左边列开始匹配。

  • 如果查询条件是 where a=1 and b=2,命中索引;
  • 如果查询条件是 where b=2 and c=3,不命中索引;
  • 如果查询条件是 where a=1 and c=3,a 列命中索引,c 列不命中索引;
  • 如果遇到范围查询(>, <, between, like),停止匹配后续列,查询条件是 where a=1 and b>2 and c=3,a 和 b 命中索引,c 不命中索引。

参考资料

相关推荐
Potato_土豆2 小时前
深入JDK 17的语法新特性
java·后端·面试
莫寒清2 小时前
MyBatis 中动态 SQL 的作用
面试·mybatis
重生之后端学习2 小时前
35. 搜索插入位置
java·数据结构·算法·leetcode·职场和发展·深度优先
努力学算法的蒟蒻2 小时前
day96(2.25)——leetcode面试经典150
算法·leetcode·面试
凉凉的知识库3 小时前
Go中的零值与空值,你搞懂了么?
分布式·面试·go
逆境不可逃3 小时前
【从零入门23种设计模式08】结构型之组合模式(含电商业务场景)
线性代数·算法·设计模式·职场和发展·矩阵·组合模式
zheshiyangyang3 小时前
前端面试基础知识整理【Day-10】
前端·面试·职场和发展
Houz-3 小时前
【13180】 计算机操作系统第一章操作系统概论——第一节操作系统概念
笔记·职场和发展·学习方法
天真小巫16 小时前
2026.2.24总结(像经营企业一样经营自己)
职场和发展