Mysql专题面试题总结

1.解释一下MySQL中InnoDB的ACID特性?

原子性(Atomicity ):事务是一个不可分割的最小操作单元,要么全部成功,要么全部失败 。InnoDB通过Undo Log实现原子性。如果事务失败,Undo Log 会记录修改前的数据,用于回滚

一致性(Consistency ):事务执行前后,事务执行前后数据逻辑一致 。例如,转账操作中总金额不变。一致性由应用层和数据库共同保证。靠原子性、隔离性、持久性共同保障。

隔离性(Isolation ):多个并发事务之间互不干扰 。InnoDB通过锁机制和MVCC(多版本并发控制)实现隔离性。

持久性(Durability ):事务提交后,修改永久保存到数据库。InnoDB通过Redo Log实现持久性。Redo Log记录修改后的数据,即使系统崩溃也能恢复。

2.MySQL中的4种事务隔离级别是什么?

读未提交(Read Uncommitted):事务可以读取其他未提交事务的修改。存在脏读、不可重复读、幻读问题。

读已提交(Read Committed):事务只能读取已提交的数据。解决脏读,但存在不可重复读和幻读(通过MVCC实现)。

可重复读(Repeatable Read):事务内多次读取同一数据结果一致。解决不可重复读,但存在幻读(InnoDB通过Next-Key Locks解决幻读)。

串行化(Serializable):所有事务串行执行,无并发问题,但性能极低。

MVCC:通过ReadView和Undo Log版本链实现多版本控制。

锁机制:如间隙锁(Gap Lock)防止幻读。

InnoDB的Next-Key Locks是记录锁(Record Lock)和间隙锁(Gap Lock)的结合:

记录锁:锁定索引中的特定行。

间隙锁:锁定索引记录之间的间隙,阻止其他事务在间隙中插入数据。

Next-Key Lock:锁定一个左开右闭区间(例如(10, 15]),包含记录本身及其之前的间隙。

3.MySQL中有哪些索引?索引的数据结构是什么?为什么使用B+树?B树和红黑树不行吗?

索引类型:主键索引、唯一索引、普通索引、联合索引、全文索引、空间索引。

数据结构:B+树:InnoDB默认的索引结构。

优势:

磁盘IO优化:B+树非叶子节点只存键值,单次IO可加载更多数据。

范围查询高效:叶子节点形成有序链表,适合范围扫描。

高度平衡:所有叶子节点在同一层,查询稳定。

对比B树:B树每个节点存数据,导致单次IO加载的键值更少,范围查询需多次回溯。

对比红黑树:红黑树是二叉树,高度更高(例如百万数据需要20层),导致更多磁盘IO。

4.用了索引还是很慢,可能是什么原因?

索引失效 :如对索引列使用函数、类型转换、OR条件包含非索引列。
回表查询 :联合索引未覆盖查询字段,需回表查主键索引。
数据分布不均 :索引区分度低(如性别字段),优化器可能选择全表扫描。
锁竞争 :事务长时间持有锁,导致查询阻塞。
统计信息不准确:优化器误判索引成本,需手动ANALYZE TABLE更新统计信息。

5.为什么树的层数不能超过3层。

B+树高度与性能:假设单页16KB,主键为BIGINT(8B),指针6B,则单页可存 16KB/(8B+6B)=1170 个键值。

3层B+树可存储 1170 * 1170 * 16 ≈ 2000万 条数据。

超过3层后,查询需要更多磁盘IO,性能显著下降。

6.sql性能优化问题,一般到达那个索引级别会比较好

索引访问类型(由EXPLAIN的type字段显示):

const:主键或唯一索引的等值查询(最优)。

ref:普通索引的等值查询。

range:索引范围扫描(如BETWEEN、>)。

index:全索引扫描(需避免)。

ALL:全表扫描(最差)。

优化目标:至少达到range级别,理想是ref或const。

7.有什么情况会索引失效?如何解决?

索引列参与运算 :如WHERE id + 1 = 10。
使用函数 :如WHERE UPPER(name) = 'ABC'。
隐式类型转换 :如字符串列用数字查询WHERE id = '100'。
OR条件包含非索引列 :如WHERE a=1 OR b=2,若b无索引则全表扫描。
联合索引未遵循最左前缀:如索引(a,b,c),但查询条件无a。

8.什么是回表?回表发生在什么索引中?什么是索引覆盖?什么是索引下推?

回表:通过普通索引查到主键后,需回主键索引查询完整数据。发生在非聚簇索引中。

索引覆盖:查询字段全部在索引中,无需回表。例如联合索引(a,b)查询a和b。

索引下推(ICP):MySQL 5.6+特性,将WHERE条件下推到存储引擎层过滤,减少回表次数。例如联合索引(a,b)查询a>1 AND b=2,存储引擎会先过滤b=2。

9.MySQL中binlog、redolog、undolog的区别?

属性 binlog redolog undolog
作用 逻辑日志,用于主从复制和数据恢复 物理日志,保证事务持久性 逻辑日志,用于事务回滚和MVCC
层级 Server层 InnoDB引擎层 InnoDB引擎层
内容 SQL语句或行变更事件 数据页的物理修改 数据修改前的版本写入
写入时机 事务提交后异步写入 事务执行中持续写入(WAL机制) 事务执行中记录

10.MySQL中索引设计原则?

选择高区分度字段 :如用户ID而非性别。
联合索引最左前缀 :将高频查询字段放在左侧。
避免过多索引 :索引增加写操作开销。
覆盖索引优化 :减少回表查询。
考虑排序和分组:索引顺序与ORDER BY或GROUP BY一致。

11.聚簇索引和非聚簇索引的区别

聚簇索引:叶子节点存储数据行(如InnoDB的主键索引)。一张表只能有一个聚簇索引。

非聚簇索引:叶子节点存储主键值(如普通索引),需回表查询数据。

12.请描述下数据库的锁,锁的分类有哪些?

按粒度:

行锁:锁定单行(InnoDB默认)。

表锁:锁定整表(如MyISAM)。

间隙锁(Gap Lock):锁定范围,防止幻读。

按模式:

共享锁(S锁):读锁,允许其他事务读。

排他锁(X锁):写锁,禁止其他事务读写。

按实现:

意向锁:表级锁,表明事务即将对行加锁。

13.update在mysql的执行流程是什么样的

连接器:验证权限。

分析器:解析SQL语法。

优化器:选择索引,生成执行计划。

执行器:

从存储引擎读取数据(若使用索引)。

调用InnoDB引擎接口修改数据。

写入Undo Log(用于回滚)和Redo Log(保证持久性)。

两阶段提交:先写Redo Log(prepare状态),再写Binlog,最后提交事务。

14.count(1) count(*) count(字段)的区别

COUNT():统计所有行数(包括NULL),优化后直接读行数。
COUNT(1):与COUNT(
)性能相同,统计所有行。

COUNT(字段):统计该字段非NULL的行数,需回表检查字段值。

count(1)底层会优化成count(*)

15.MySQL中索引类型有哪些?

主键索引、唯一索引、普通索引、联合索引、全文索引(FULLTEXT)、空间索引(SPATIAL)。

16.介绍一下MVCC机制?记忆锚点:

核心:隐藏字段 + undo log 版本链 + Read View→无锁读;

流程:Read View 判断版本可见性,遍历版本链找可见数据。

面试表达模板:

"事务的隔离性靠锁和 MVCC,MVCC 是多版本并发控制,能实现'读不加锁,写不阻塞读' ,底层有 3 个核心组件:

第一个是隐藏字段,每行数据有 trx_id(最后修改的事务 ID)和 roll_pointer(指向 undo log 的指针);
第二个是 undo log 版本链,每次修改数据都
会生成新的 undo log,用 roll_pointer 连起来
,比如数据被事务 1、2 修改,版本链就是事务 2→事务 1→原始数据;

第三个是 Read View,事务启动时生成的快照,记录当前活跃的事务 ID。比如事务 A 启动时,Read View 里活跃事务 ID 是 [2,3],查数据时会从最新版本开始遍历版本链:如果 trx_id 比活跃事务最小 ID 还小,说明这个事务已经提交了,数据可见,就返回;如果 trx_id 在活跃事务里,说明事务还没提交,数据不可见,继续找下一个版本。这样就能保证事务 A 看到的是启动时的快照,不会被其他事务的修改干扰,实现隔离性。"

17.描述一下MySQL主从复制过程?如何解决主从复制延迟?

主库:将数据变更写入Binlog。

从库:IO线程拉取Binlog到中继日志(Relay Log)。

从库:SQL线程重放Relay Log中的事件。

延迟解决:

并行复制(按库或按事务分组)。

半同步复制(主库等待至少一个从库确认)。

分库分表减少单库压力。

18.MySQL中死锁问题如何解决?如何排查慢SQL问题?

死锁解决:

设置innodb_lock_wait_timeout(锁超时时间)。

启用innodb_deadlock_detect(自动检测并回滚代价小的事务)。

慢SQL排查:

开启慢查询日志(slow_query_log)。

使用EXPLAIN分析执行计划。

优化索引或重写SQL。

19.如何优化MySQL中深度分页?

问题:LIMIT 1000000,10需扫描前100万行。

优化方案:

使用覆盖索引+子查询:SELECT * FROM table WHERE id > (SELECT id FROM table LIMIT 1000000,1) LIMIT 10。
记录上次查询的最大ID:WHERE id > last_max_id LIMIT 10。

20.如何优化一个大规模的数据库系统?

垂直拆分:按业务模块分库(如用户库、订单库)。

水平拆分:分表(如按用户ID哈希)。

读写分离:主库写,从库读。

缓存:使用Redis缓存热点数据。

硬件优化:SSD、增加内存。

SQL优化:避免全表扫描,减少JOIN操作。

相关推荐
qq_334563552 小时前
CSS如何实现移动端文字转阴影效果_通过text-stroke模拟描边
jvm·数据库·python
数厘2 小时前
2.18 sql排序查询(ORDER BY、ASC、DESC)
数据库·sql·oracle
m0_377618232 小时前
mysql数据库如何通过调整读取策略提升性能_开启innodb_read_ahead
jvm·数据库·python
2301_814809862 小时前
MongoDB开启认证后应用程序出现断连假死现象
jvm·数据库·python
m0_678485452 小时前
mysql如何对比备份数据与线上数据_编写自动化校验脚本
jvm·数据库·python
石工记2 小时前
postgresql18 安装-运行
数据库·postgresql
DashVector2 小时前
AI Agent 接入 Zvec (一):MCP 篇
数据库·人工智能·后端
2401_865439632 小时前
C#怎么将控制台输出保存到TXT_C#如何重定向输出流【源码】
jvm·数据库·python
2301_815279522 小时前
Golang和Node.js哪个适合后端_Golang Node对比教程【实战】
jvm·数据库·python