新闻详情

新闻详情

首页 / 资讯中心 / 详情

MySQL面试题深度解析:从慢查询到索引、事务与锁的实战指南

发布时间:2026/10/2 5:51:43来源:尧图网络
MySQL面试题深度解析:从慢查询到索引、事务与锁的实战指南
简介这是一份面向后端开发求职者与在校学生的 MySQL 面试知识点总结文档围绕数据库原理与索引机制展开帮助读者系统梳理高频考点、补齐知识盲区。内容涵盖关系型与非关系型数据库的区别、一条 SQL 语句从连接器到执行器的完整执行流程、索引的使用原因与哈希表/有序数组/搜索树三种底层数据结构并深入对比 MyISAM 与 InnoDB 的 B 树索引实现差异、聚簇索引与二级索引的叶子节点存储方式以及覆盖索引、索引下推、change buffer、redo log 与 binlog 等进阶话题还整理了模糊匹配、函数计算、隐式转换、OR 条件等导致索引失效的常见场景。资源包共 1 个 docx 文件约 40KB以问答形式组织条理清晰便于速查背诵。目前已有 251 人学习下载适合面试前集中复习或日常查漏补缺使用。1. MySQL 面试题到底在考什么从一条慢查询说起很多人背 MySQL 面试题的方式是打开一份 PDF从「什么是事务」开始往下刷刷到「MVCC 原理」就卡住最后记住的只有几个名词。但真实面试里面试官往往不会直接问你「说说索引」而是丢一条 SQL 过来「这条查询为什么慢你怎么优化」——这才是 MySQL 面试题的核心考法不是考你背了多少概念而是考你能不能把概念落到一条具体的 SQL、一张具体的表、一次具体的执行计划上。MySQL 面试题覆盖的范围其实很集中索引与执行计划、事务与锁、日志与持久化、主从复制与高可用、分库分表与连接池。这些点看起来散但底层是一条线串起来的——数据怎么存、怎么查、怎么保证不出错。你如果只背结论面试官换个场景追问一句就露馅你如果理解了这条线大部分题都能自己推出来。这篇笔记就按这条线走一遍把每类高频题拆成「原理是什么、怎么验证、参数怎么调、坑在哪」让你不只是能答还能在本地跑出来看。2. 索引与执行计划面试第一道坎怎么过2.1 从 B 树到最左前缀为什么你的索引没走MySQL 面试题里出现频率最高的就是索引。面试官问「为什么加了索引还是慢」八成是因为索引没走对。要理解这个得先知道 InnoDB 的索引结构是 B 树——非叶子节点只存键值叶子节点存数据并用链表串起来。这个结构决定了三件事等值查询快、范围查询快、但前缀模糊查询like %xx走不了索引。更常考的是联合索引的最左前缀原则。假设你建了idx_a_b_c (a, b, c)那么where a1、where a1 and b2、where a1 and b2 and c3都能走索引但where b2、where b2 and c3走不了。原因在于 B 树是按 a 先排序、a 相同再按 b 排序、b 相同再按 c 排序的你跳过 a 直接找 b树没法定位。这里有个容易被追问的点where a1 and c3能不能走索引答案是能走但只用到 a 这一列c 用不上。因为 a 确定后c 在树里不是连续有序的。面试官如果追问「那怎么优化」你可以说把 c 提到联合索引第二位或者建覆盖索引。验证这些结论最直接的方式是EXPLAIN。下面这条命令是必须会的-- 建一张测试表模拟订单场景 CREATE TABLE t_order ( id BIGINT PRIMARY KEY AUTO_INCREMENT, user_id BIGINT NOT NULL, status TINYINT NOT NULL DEFAULT 0, amount DECIMAL(10,2) NOT NULL, created_at DATETIME NOT NULL, KEY idx_user_status (user_id, status) ) ENGINEInnoDB; -- 用 EXPLAIN 看执行计划 EXPLAIN SELECT * FROM t_order WHERE user_id 1001 AND status 1;执行后重点看几个字段type最好是ref或range出现ALL就是全表扫描key显示实际用的索引rows是预估扫描行数Extra里出现Using filesort或Using temporary就要警惕。如果Extra是Using index说明是覆盖索引不用回表这是最好的情况。参数上有一个常被忽略的optimizer_switch。MySQL 5.6 之后有索引下推index condition pushdown默认开启。它能把 where 条件下推到存储引擎层过滤减少回表次数。你可以用SET optimizer_switchindex_condition_pushdownoff关掉对比效果面试时能说出这个细节会加分。2.2 用 EXPLAIN 和慢查询日志定位问题一套可复现的排查流程光会看 EXPLAIN 还不够面试官常问「线上怎么发现慢查询」。标准答案是慢查询日志加pt-query-digest或者performance_schema。我一般按这个流程走第一步确认慢查询日志开着SHOW VARIABLES LIKE slow_query_log; SHOW VARIABLES LIKE long_query_time;如果slow_query_log是 OFF用SET GLOBAL slow_query_log ON;打开long_query_time默认 10 秒线上一般调到 1 秒甚至 0.5 秒。注意这个参数是会话级的改完只对新连接生效。第二步用mysqldumpslow或pt-query-digest聚合分析。mysqldumpslow -s t -t 10 slow.log能按执行时间排出前 10 条。这一步的目的是找出「哪类 SQL 最耗资源」而不是逐条看。第三步对找出的 SQL 跑 EXPLAIN看是否走索引、扫描行数是否合理。如果rows远大于实际返回行数说明索引选择性差考虑换索引或加联合索引。第四步用SHOW PROFILE看具体耗时在哪个阶段SET profiling 1; SELECT * FROM t_order WHERE user_id 1001 AND status 1; SHOW PROFILES; SHOW PROFILE FOR QUERY 1;SHOW PROFILE会列出Sending data、Sorting result等阶段的耗时。如果Sending data占比高通常是回表太多或返回数据量大如果Sorting result高说明有 filesort需要优化排序字段的索引。这里有个血泪经验很多人看到typeALL就急着加索引但忽略了rows很小的情况。如果一张表只有几百行全表扫描比走索引还快因为走索引要回表。面试时能说出「小表全扫不一定慢」这个边界说明你真跑过。3. 事务与锁MVCC 和间隙锁到底怎么答3.1 一条 update 背后的锁从行锁到间隙锁事务和锁是 MySQL 面试题里最容易翻车的部分。面试官问「什么是 MVCC」你背出「多版本并发控制通过 undo log 和 read view 实现」只能算及格。真正拉开差距的是追问「RR 隔离级别下select ... for update加的是什么锁」InnoDB 的锁按粒度分行锁和表锁行锁又分记录锁Record Lock、间隙锁Gap Lock、临键锁Next-Key Lock。在 RR 隔离级别下select ... for update默认加的是临键锁也就是记录锁加间隙锁锁住记录本身和它前面的间隙。这样做的目的是防止幻读。举个例子表里 id 有 1、5、10 三条记录你执行select * from t where id 3 for update锁住的是 (3,5]、(5,10]、(10,∞) 这几个区间。这时候另一个事务插入 id7 会被阻塞插入 id2 不会。这就是间隙锁的作用。但间隙锁有个坑它只在 RR 级别生效RC 级别下没有间隙锁只有记录锁。所以如果你的业务从 RC 切到 RR可能会突然出现大量锁等待。面试时如果被问到「为什么线上锁等待突然增多」先确认隔离级别有没有变。验证锁等待可以用这两张表-- 会话 1 BEGIN; SELECT * FROM t_order WHERE user_id 1001 FOR UPDATE; -- 会话 2会阻塞 BEGIN; SELECT * FROM t_order WHERE user_id 1001 FOR UPDATE; -- 另开会话查锁等待 SELECT * FROM performance_schema.data_lock_waits; SELECT * FROM information_schema.innodb_trx;innodb_trx里能看到当前运行的事务、锁等待时间、阻塞的 SQL。data_lock_waits是 MySQL 8.0 的表5.7 用innodb_lock_waits。这一步在面试里能说出来说明你真排查过线上问题。3.2 MVCC 的 read view 怎么读三个参数决定可见性MVCC 的核心是 read view。每次快照读普通 select会生成一个 read view里面有几个关键字段m_ids当前活跃事务 ID 列表、min_trx_id最小活跃事务 ID、max_trx_id下一个要分配的事务 ID。判断某行版本是否可见的规则是如果行的trx_id小于min_trx_id说明这个版本在 read view 创建前就提交了可见。如果行的trx_id大于等于max_trx_id说明这个版本是 read view 创建后才开始的不可见。如果trx_id在m_ids里说明事务还活跃不可见。否则可见。这套规则面试时能画出来最好画不出来就用文字说清楚。常被追问的是「RR 和 RC 的 read view 有什么区别」——RR 只在第一次快照读时生成 read view之后复用RC 每次快照读都重新生成。这就是为什么 RR 能可重复读RC 不能。这里有个容易答错的点MVCC 只解决快照读的并发当前读select ... for update、update、delete还是要加锁。面试官如果问「MVCC 能解决幻读吗」标准答案是「快照读下能当前读下不能需要间隙锁配合」。4. 日志与持久化redo log 和 binlog 的配合4.1 两阶段提交一条 update 到底写了几个文件MySQL 面试题里关于日志的高频问题是「一条 update 语句的执行流程」。完整答案是先写 undo log用于回滚再写 redo logprepare 状态再写 binlog最后提交 redo logcommit 状态。这就是两阶段提交。为什么要两阶段提交因为 redo log 和 binlog 是两套独立的日志如果不协调可能出现 redo log 写了但 binlog 没写或者反过来。主从复制靠 binlog崩溃恢复靠 redo log两者不一致就会导致主从数据不一致或恢复后数据丢失。redo log 是物理日志记录「在某个数据页做了什么修改」循环写空间固定。binlog 是逻辑日志记录「执行了什么 SQL」或「行变更」追加写空间不固定。面试时能说清这两个区别基本就过关了。参数上要关注innodb_flush_log_at_trx_commit和sync_binlog。前者控制 redo log 的刷盘策略0 是每秒刷1 是每次提交刷2 是写到 OS cache 每秒刷。后者控制 binlog 刷盘0 是交给系统1 是每次提交刷。线上一般设innodb_flush_log_at_trx_commit1和sync_binlog1保证不丢数据但性能会降。如果业务能容忍少量丢失可以设 2 和 0 换性能。4.2 用 mysqlbinlog 验证主从数据一致性面试官问「怎么验证主从一致」很多人只会说SHOW SLAVE STATUS看Seconds_Behind_Master。但这个值不准主库压力大时它会飘。更可靠的方式是用pt-table-checksum或者直接解析 binlog 对比。一个可复现的验证方法是在主库执行一批写操作记录 binlog 位置然后在从库用mysqlbinlog解析对应区间的日志看是否都应用了。# 在主库查看当前 binlog 位置 mysql -e SHOW MASTER STATUS\G # 执行一批写操作 mysql -e INSERT INTO t_order (user_id, status, amount, created_at) VALUES (2001, 1, 99.00, NOW()); # 在从库查看复制状态 mysql -e SHOW SLAVE STATUS\G | grep -E Slave_IO_Running|Slave_SQL_Running|Seconds_Behind_MasterSlave_IO_Running和Slave_SQL_Running都必须是 Yes任何一个 No 都说明复制断了。Seconds_Behind_Master只能参考真正判断延迟要看Relay_Log_Pos和Exec_Master_Log_Pos的差值。如果复制断了常见原因是主键冲突或从库写入。排查步骤是看Last_SQL_Error然后决定是跳过这个事务SET GLOBAL SQL_SLAVE_SKIP_COUNTER1还是重建从库。跳过事务是后悔药能不用就不用因为会导致数据不一致。5. 避坑与排查MySQL 面试题里最容易答错的五个点5.1 坑一以为加了索引就一定走现象明明建了索引EXPLAIN 显示typeALL。原因索引列上用了函数、隐式类型转换、或者最左前缀没满足。比如where date(created_at) 2026-01-01用不了索引因为对列做了函数运算where user_id 1001如果 user_id 是 bigint字符串会隐式转换也可能不走索引。解决把函数移到等号右边比如where created_at 2026-01-01 and created_at 2026-01-02类型保持一致数字列就传数字。5.2 坑二RR 级别下以为没有幻读现象面试时答「RR 解决了幻读」被追问「那为什么还能插入」。原因RR 只解决了快照读的幻读当前读for update下如果没有间隙锁还是能插入。而且间隙锁只在 RR 下生效RC 下没有。解决答的时候区分快照读和当前读说清间隙锁的作用范围。如果面试官继续追问「间隙锁有什么代价」答「会增加锁冲突概率可能死锁」。5.3 坑三把 redo log 和 binlog 搞混现象被问「崩溃恢复用哪个日志」答成 binlog。原因没理解两套日志的分工。redo log 是 InnoDB 层的负责崩溃恢复binlog 是 Server 层的负责主从复制和数据归档。解决记住「redo 管恢复binlog 管复制」。再记一个细节redo log 是循环写的binlog 是追加写的。5.4 坑四连接池配得越大越好现象线上连接数一高就报Too many connections于是把max_connections调到几千。原因连接数不是越大越好每个连接占内存而且上下文切换开销大。MySQL 默认max_connections151调到几千可能导致内存耗尽。解决先看Threads_connected和Threads_running如果 running 远小于 connected说明大量连接空闲应该优化连接池配置而不是加连接数。连接池的maxPoolSize一般设 CPU 核数的 2 到 4 倍配合connectionTimeout和idleTimeout。5.5 坑五分库分表后还按单表思路写 SQL现象分库分表后查询变慢甚至查不到数据。原因分片键没选对或者跨分片查询。比如按 user_id 分片但查询条件只有 order_id就要扫所有分片。解决分片键要选查询频率最高的字段尽量让查询能定位到单个分片。跨分片查询用中间件聚合或者建冗余表。面试时如果被问「分库分表后怎么分页」答「先在各分片查再聚合或者用二次查询法」。6. 进阶技巧用 performance_schema 定位锁等待和慢 SQL面试里如果能把performance_schema用起来基本能超过八成候选人。它比慢查询日志更实时能看到当前正在执行的 SQL、锁等待、IO 情况。下面这套查询是我排查线上问题时最常用的-- 查看当前正在执行的 SQL按耗时排序 SELECT t.PROCESSLIST_ID, t.PROCESSLIST_USER, t.PROCESSLIST_TIME, t.PROCESSLIST_STATE, t.PROCESSLIST_INFO FROM performance_schema.threads t WHERE t.PROCESSLIST_INFO IS NOT NULL ORDER BY t.PROCESSLIST_TIME DESC LIMIT 10; -- 查看锁等待关系 SELECT w.REQUESTING_ENGINE_TRANSACTION_ID AS waiting_trx, w.BLOCKING_ENGINE_TRANSACTION_ID AS blocking_trx, w.REQUESTING_THREAD_ID, w.BLOCKING_THREAD_ID FROM performance_schema.data_lock_waits w; -- 查看当前事务 SELECT trx_id, trx_state, trx_started, trx_mysql_thread_id, trx_query FROM information_schema.innodb_trx ORDER BY trx_started;第一段查当前活跃 SQLPROCESSLIST_TIME是执行秒数超过 5 秒就要关注。第二段查锁等待能直接看出谁在等谁。第三段查事务trx_state是 RUNNING 或 LOCK WAITtrx_query是当前 SQL。参数上要确认performance_schema是开的SHOW VARIABLES LIKE performance_schema;默认 ON。如果 OFF需要重启并加配置。另外performance_schema本身有内存开销线上如果内存紧张可以关掉部分 consumer。一个具体技巧如果发现锁等待先看blocking_trx对应的线程 ID用KILL杀掉阻塞源。但杀之前要确认这个事务是不是重要业务别把正常的长事务误杀了。我一般会先看trx_started如果跑了很久还没提交大概率是代码里忘了 commit 或者事务范围太大。最后说个我自己的习惯每次面试前我会在本地起一个 MySQL把索引、事务、锁、日志这几个点各跑一遍用 EXPLAIN 和 performance_schema 看实际结果。背下来的答案和跑出来的结果在面试官追问时的底气完全不一样。希望帮到你。本文还有配套的精品资源点击获取
网站建设高端定制企业官网
RELATED

相关资讯

更多精彩内容,欢迎继续阅读

较早相关资讯

最新相关资讯

ESP32蓝牙卫星追踪云台:SGP4轨道预测+DRV8825步进控制实战 2026/10/2 7:32:06

ESP32蓝牙卫星追踪云台:SGP4轨道预测+DRV8825步进控制实战

1. 项目概述:一个用蓝牙遥控的卫星追踪云台,到底在解决什么问题?“Look4sat蓝牙追星云台”——光看名字,就能嗅到一股硬核DIY混合着天文观测与嵌入式开发的独特气味。它不是市面上那种靠手机App点几下就自动转的消费级云台&#x…

阅读更多 →
Multisim 14.3可控安装指南:校验、兼容性与License激活 2026/10/2 7:32:05

Multisim 14.3可控安装指南:校验、兼容性与License激活

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

阅读更多 →
Java+Swing+Mysql员工工资管理系统实战:从建表到算薪完整教程 2026/10/2 7:31:52

Java+Swing+Mysql员工工资管理系统实战:从建表到算薪完整教程

简介:这是一套面向Java初学者与课程设计学习者的员工工资管理系统完整源码,基于Java Swing桌面端与MySQL数据库开发,适合作为毕业设计、课程作业或SwingJDBC综合练习的参考方案。系统分为管理员与普通用户两种角色:管理员可对员工…

阅读更多 →
ESP32 IRAM优化实战:释放37KB指令内存的完整方案 2026/10/2 7:31:52

ESP32 IRAM优化实战:释放37KB指令内存的完整方案

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

阅读更多 →
SpringBoot+微信小程序实战:打造智能社交网络平台全攻略 2026/10/2 7:31:52

SpringBoot+微信小程序实战:打造智能社交网络平台全攻略

能组合出这种标题的项目,十有八九是毕设、课设或者练手私活,而“SpringBoot 微信小程序 社交平台”又恰好是这几年被问得最频繁的组合。我做过几个类似需求的系统,也帮人排查过不少问题,先说结论:这个题目看着常规&a…

阅读更多 →
一键开关机芯片选型指南:四维度搞定低功耗电子开关设计 2026/10/2 7:31:39

一键开关机芯片选型指南:四维度搞定低功耗电子开关设计

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

阅读更多 →

今日资讯

本周资讯

本月资讯

看完文章仍有疑问?

联系尧图顾问,获取一对一建站咨询

立即免费咨询 📞 400-888-8888
📞 ✉