news 2026/9/30 3:35:20

MySQL核心复习:DQL多表查询、事务ACID与索引优化

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
MySQL核心复习:DQL多表查询、事务ACID与索引优化

最近把黑马程序员的 MySQL 课程第三、四章又完整过了一遍,越复习越觉得这两章才是整个 MySQL 学习的胜负手。前两章是建库建表、增删改查这种基础动作,到了第三、四章,才开始真正接触数据操作的核心:查询的深度展开、表与表之间的关系、约束如何保证数据完整性、事务与索引又是怎么影响性能的。如果你学完这两章有“懂了但做题不会、面试不会”的感觉,这篇复习笔记应该能帮你把知识串起来。

我按自己复习的顺序来写,把这两个章节的核心内容、踩过的坑、高频面试题和一套可以直接自测的 SQL 练习全整理在里面。无论你是跟着黑马视频学的,还是别的教程入的门,只要学到这附近,这份笔记都适用。

1. 先搞清楚第三、四章到底在讲什么

1.1 这两章覆盖的核心范围

不同版本的黑马 MySQL 课程,章节切分可能略有差异,我复习的这个版本里,第三章是DQL 查询进阶,第四章是约束、表关系、事务、索引。如果你用的资料章节顺序不一样也别慌,核心内容基本就是这几大块:

  • 第三章:DQL 的排序、聚合函数、分组、分页,多表查询中的内连接、外连接、自连接,以及子查询。
  • 第四章:非空、唯一、主键、默认、外键这五大约束,表之间的一对多、多对多、一对一关系,事务的 ACID 特性与隔离级别,索引的分类、底层结构和使用原则。

这个范围意味着什么?意味着你从“会写单表增删改查”过渡到了“能处理真实业务场景下的复杂查询和数据一致性”。面试里被问烂的慢查询优化、事务隔离、索引失效,根源都在这一章里。可以说,前面是教你用 SQL 说话,这两章是教你用 SQL 把事办漂亮。

1.2 高效复习顺序与误区提醒

我复习的时候踩过一个很大的误区——先刷视频再写代码,结果看完第三章多表查询的三种连接方式,脑子以为会了,手一写就报错。后来我调整了顺序,亲测有效:

  1. 先建两张有外键关系的表(比如部门表、员工表),把数据灌进去。
  2. 再去看视频或者笔记里的查询语法,每学一种连接方式就立刻在本地跑一条对应的 SQL。
  3. 第 4 章重点放在理解“为什么”,为什么要有约束、为什么事务要有隔离级别、为什么索引要用 B+ 树而不是链表,带着问题去复习,记忆的牢固程度完全不一样。

这个顺序的好处是:你手里有真实的数据表,各种连接、聚合、子查询的效果一眼就能看出来,不用靠脑子空想。很多同学复习时觉得“看懂了”但不会做题,就是因为缺少这一层动手验证。

2. 第三章核心复盘:DQL 查询进阶

2.1 五个子句的执行顺序,这是整章的命脉

DQL 完整语法可以浓缩成一句话:FROM → WHERE → GROUP BY → HAVING → SELECT → ORDER BY → LIMIT。这是整章节里最值得背的内容,因为 90% 的 SQL 报错都跟这个顺序有关。

我举个例子,假设有员工表 emp(id, name, age, salary, dept_id),想查出平均工资大于 5000 的部门,并且按平均工资降序排:

SELECT dept_id, AVG(salary) AS avg_sal FROM emp WHERE salary IS NOT NULL GROUP BY dept_id HAVING avg_sal > 5000 ORDER BY avg_sal DESC;

注意这里的细节:HAVING 里可以直接用 avg_sal 这个别名,WHERE 里却不能用。原因是 WHERE 是在 GROUP BY 之前执行的,此时别名的“计算”还没发生。很多新手在 WHERE 里写别名导致报错,就是因为没理解执行顺序。

再比如分页,LIMIT 一定是在最后一步执行。分页公式是(页码 - 1)* 每页条数,比如每页 10 条查第 2 页,就是 LIMIT 10, 10,其中的第一个 10 是偏移量。这个公式没啥技术含量,但要自己动手算一次,因为面试笔试真会考。

2.2 聚合、分组、排序、分页的组合套路

聚合函数常用的就五个:COUNT、SUM、AVG、MAX、MIN。这里最容易出问题的是 COUNT 的细节。COUNT(*) 和 COUNT(字段) 在思路上完全不同,前者统计行数,后者统计字段非空值的个数。如果字段允许为 NULL,用 COUNT(字段) 会少算,业务上就出大事了。

分组查询里,一个经典难点是“SELECT 的字段必须要么在 GROUP BY 里,要么被聚合函数包裹”。比如上面例子里的 dept_id 在 GROUP BY 里,AVG(salary) 是聚合结果,所以没问题。但如果你在 GROUP BY dept_id 时,把 emp.name 也放到 SELECT 列表里,MySQL 在 ONLY_FULL_GROUP_BY 模式下会直接报错,因为一个部门里有多个人,数据库不知道该展示哪个名字。

排序和分页通常结伴出现。常见场景是“查工资最高的前三名”:

SELECT name, salary FROM emp ORDER BY salary DESC LIMIT 3;

注意 ORDER BY 的执行顺序是在 SELECT 之后,所以可以直接用 SELECT 里的别名排序。这部分内容看似简单,但实际工作中写分页报表,排序字段搞错,数据一多就全乱了。

2.3 多表查询:内连接、外连接、自连接怎么选

第三第四章我用办公场景打个比方:单表查询像是你只看一个人的档案,多表查询像是把部门墙上的人员名单和每个人的档案合在一起看。三张连接方式,各有各的用途:

连接类型返回结果典型场景
INNER JOIN两表都匹配的行查“有部门归属的员工”
LEFT JOIN左表全部 + 右表匹配,右表无匹配则 NULL查“所有部门下的员工,空部门也保留”
RIGHT JOIN右表全部 + 左表匹配,左表无匹配则 NULL与 LEFT JOIN 互为反向,实际用得少
自连接表和自己连接查员工对应的上级姓名

自连接是很多新手最懵的点。看代码最容易理解:

SELECT e.name AS '员工', m.name AS '上级' FROM emp e LEFT JOIN emp m ON e.manager_id = m.id;

这里把 emp 表起了两个别名 e 和 m,一张表扮演“员工表”,一张表扮演“上级表”。自连接的核心就是用别名把同一张表拆成两个逻辑角色。记住了这一点,后面学树形结构、评论回复这种业务时就很轻松。

2.4 子查询的分类与应用场景

子查询分四类:标量子查询(结果是一个值)、行子查询(结果是一行)、列子查询(结果是一列)、表子查询(结果是一张临时表)。面试时高频考的是“查工资高于平均工资的员工”:

SELECT name, salary FROM emp WHERE salary > (SELECT AVG(salary) FROM emp);

这个括号里的子查询就是标量子查询,先算平均工资,再拿每一行工资去比。想查“每个部门工资最高的员工”,常常用表子查询配合连接:

SELECT e.name, e.salary, e.dept_id FROM ( SELECT dept_id, MAX(salary) AS max_sal FROM emp GROUP BY dept_id ) t JOIN emp e ON e.dept_id = t.dept_id AND e.salary = t.max_sal;

子查询和 JOIN 经常可以互相转换,复习时可以拿同一道题用两种写法都做一遍,体会它们的差异。子查询的好处是逻辑清晰,先“圈定”一个范围再去主表里找;JOIN 的好处是效率在多数场景下更高,尤其数据量大时。面试如果问你“子查询和多表联查的取舍”,这就是核心答案。

3. 第四章核心复盘:约束、事务与索引

3.1 五大约束的作用与建表规范

四个章节里逻辑最像“规则”的就是约束。约束的本质是数据库不让非法数据进来,相当于公司的门禁系统。五大约束分别是:

  • NOT NULL:非空约束,防止字段存 NULL。
  • UNIQUE:唯一约束,字段值不能重复。
  • PRIMARY KEY:主键约束,非空 + 唯一,一张表只能有一个。
  • DEFAULT:默认值约束,不写就使用默认值。
  • FOREIGN KEY:外键约束,关联另一张表的主键。

建表时常见写法是:

CREATE TABLE dept ( id INT PRIMARY KEY AUTO_INCREMENT COMMENT '部门ID', name VARCHAR(20) NOT NULL UNIQUE COMMENT '部门名称' ); CREATE TABLE emp ( id INT PRIMARY KEY AUTO_INCREMENT COMMENT '员工ID', name VARCHAR(20) NOT NULL COMMENT '姓名', age INT DEFAULT 20 COMMENT '年龄,默认20', salary DECIMAL(10,2) COMMENT '薪资', dept_id INT COMMENT '部门ID', CONSTRAINT fk_dept FOREIGN KEY (dept_id) REFERENCES dept(id) );

这里我多说一句外键的坑。加了外键之后,插入子表记录时,关联的父表记录必须已经存在;删除父表记录时,如果子表有引用,会被拒绝或级联删除。复习时强烈建议把 ON DELETE CASCADE 和 ON DELETE SET NULL 各建一张表试一遍,不然面试里“外键级联怎么设置”十有八九答不全。

3.2 事务 ACID 与隔离级别

第四章里,事务是面试权重最高的内容。事务解决的业务场景很典型:转账,A 扣 100,B 加 100,中间任何一步失败,所有操作都回滚。

事务四特性 ACID 要能用自己的话说清楚:

  • 原子性:一个事务里的操作要么全成功,要么全失败,不能只执行一半。
  • 一致性:事务开始前和结束后,数据整体处于合法状态,比如账户余额不能变负数。
  • 隔离性:多个事务并发执行时互不干扰。
  • 持久性:事务提交后,数据修改要永久保存,不会因为重启就丢。

并发事务会带来三类问题:脏读(读到别人未提交的数据)、不可重复读(同一查询前后两次结果不同)、幻读(同一范围查询前后两次行数不同)。为了应对这些问题,MySQL 提供了四种隔离级别:

隔离级别脏读不可重复读幻读
READ UNCOMMITTED可能可能可能
READ COMMITTED避免可能可能
REPEATABLE READ(默认)避免避免可能(InnoDB 快照读下基本避免)
SERIALIZABLE避免避免避免

MySQL 默认是可重复读,Oracle 默认是读已提交。这个区别面试常考,原因是 MySQL 在可重复读级别下能通过 MVCC 多版本并发控制,让普通查询走快照读,很大程度上规避了幻读问题。我复习时的体会是,不用死背隔离级别名字,先把三类问题的场景记住,再反推每个级别解决了什么,考试和面试都够用。

3.3 索引底层结构与使用原则

索引是我认为第四章里实操价值最大的部分。很多人对这个概念的理解停留在“索引能让查询变快”这句话上,但如果面试官追问“为什么用 B+ 树而不用哈希、链表”,就容易卡壳。

MySQL 默认存储引擎 InnoDB 用的是 B+ 树索引。B+ 树的特点是:叶子节点存数据,并且叶子节点之间用指针串联,天然适合范围查询;非叶子节点只存索引字段,一个节点能容纳成百上千个键,树的高度低,磁盘 I/O 次数少。对比哈希索引,单条等值查询确实快,但范围查询就完全没法利用了。

索引不是越多越好。我整理了一套实用判断逻辑:

  • 等值查询、范围查询、排序、分组、关联字段都值得建索引。
  • 数据量非常小的表(几千行以内),全表扫描可能比走索引还快,不用急着建。
  • 频繁更新的列不建议建索引,因为每次更新都要同步维护索引树。
  • 区分度低的列,比如性别只有男和女,建索引的收益很小。

建索引的语法很简单:

CREATE INDEX idx_emp_salary ON emp(salary);

但更值得记的是联合索引的最左前缀法则。比如建了联合索引 (name, age, salary),那么查询条件里必须以 name 开头才能命中索引,只有 age 和 salary 条件时索引用不上。这个知识点我在复习时反复验证过,确实是面试和工作中最容易被忽视的优化点。

3.4 锁机制与 MVCC 的简单理解

这一小节是第四章的延展,黑马课程里可能讲得不多,但面试题里频繁出现,热搜词里 mysql 锁原理及面试题也都是这个方向。简单说,InnoDB 支持行锁和表锁两种粒度的锁,行锁又分共享锁和排他锁。共享锁允许多个事务一起读,排他锁则一个事务独享,其他事务只能等。

为什么要有锁?本质是为了保证隔离性。事务 A 在修改一行时,事务 B 如果同时改,就会冲突。锁就是解决这个冲突的秩序规则。幻读的终极解决方案,在 InnoDB 里还可以靠间隙锁实现,也就是不仅锁住已有记录,还锁住记录之间的“空隙”,防止别人插入新记录。

MVCC 则可以理解成一种更聪明的多版本管理机制。多个事务并发读时,每个事务都能看到自己那个时间点的数据快照,读操作不会被写操作阻塞,大大提升了并发度。把锁和 MVCC 放在一起看,才能理解 MySQL 为什么能同时保证隔离性和一定的并发性能。

4. 高频面试题与避坑实录

4.1 面试题速查表

复习阶段最需要一份“背题清单”,我把自己在面试被问过和题库里见过的高频题整理成了速查表,每题都附了答题要点:

高频问题答题要点加分表达
MySQL 默认隔离级别是什么?REPEATABLE READ因为 InnoDB 的 MVCC 快照读解决了部分幻读
事务的隔离级别有哪些?读未提交、读已提交、可重复读、串行化分别说出脏读、不可重复读、幻读的解决情况
索引为什么用 B+ 树?树高度低、磁盘 I/O 少、叶子节点有序适合范围查询对比哈希和二叉搜索树说出劣势
哪些情况索引会失效?函数运算、隐式类型转换、前缀模糊匹配、OR 条件含非索引列举例说明每一种情况
内连接和左外连接有什么区别?内连接只返回匹配行,左连接返回左表所有行用两表实际数据举例说明 NULL 补位
如何优化慢 SQL?EXPLAIN 看执行计划、检查索引、减少 * 查询、避免大范围扫描说出 extra 里的 using filesort 含义

这些题目单看都不难,难的是面试现场用口语讲清楚。我建议复习时对着镜子或录音把每道题说一遍,能口述出来的才是真会。

4.2 实操中容易踩的坑

我把自己实操过程中踩过的坑整理出来,有些坑真的很隐蔽。

第一个坑是连接方式的误用。统计所有部门的人数时,如果直接用 INNER JOIN,空部门会被直接过滤掉。正确做法是 LEFT JOIN,再在 COUNT 里对员工字段做判断。业务上“没有员工的部门要不要展示”,这是产品逻辑和 SQL 写法的结合,只在嘴边说不练很容易在笔试里翻车。

第二个坑是事务隔离级别和锁的理解停留在字面。比如“可重复读下不会出现幻读”这句话,严谨说法是在 InnoDB 的快照读下基本不会,但如果当前读结合锁,仍可能出现。面试官问深一层就会卡住。

第三个坑是索引失效的真实触发条件。最典型的是在索引列上使用函数或隐式类型转换,比如 WHERE salary + 0 > 5000,索引直接失效。还有模糊查询 LIKE '%张',左前缀带百分号,B+ 树就没法走索引了。整理一个“失效条件清单”贴在手边,写 SQL 前自查一遍,能避掉至少一半的慢查询。

4.3 复习自测方法

我最推荐的自测方法是用命令行或 DBeaver 连上本地 MySQL,自己准备两张表,然后不看答案默写二十道题。先写建表语句,再插入数据,再逐条验证查询结果。比如:

  1. 查每个部门的平均工资,且平均工资大于 5000。
  2. 查工资最高的前三名员工。
  3. 查没有部门归属的员工。
  4. 查每个部门的人数,空部门显示 0。
  5. 查工资高于公司平均工资的员工。
  6. 查员工和上级的姓名。
  7. 用商品表和订单表做一对多关联,查下单最多的商品。

这些题能全做对,第三章基本就过关了。第四章的自测方向则是:给一个订单模块设计表结构,说清楚哪张表加什么约束、哪些字段该建索引、事务在什么步骤开始和提交、如何设置隔离级别。把“写 SQL”和“口头设计”都过了,复习才算闭环。

5. 实战建议:把复习变成动手能力

5.1 一套可以直接抄的自测练习

这里给出一套我整理的自测 SQL 模板,建议直接复制到本地执行。先建表和插数据,再逐题做:

-- 建库 CREATE DATABASE review_db DEFAULT CHARSET utf8mb4; USE review_db; -- 部门表 CREATE TABLE dept ( id INT PRIMARY KEY AUTO_INCREMENT, name VARCHAR(20) NOT NULL ); -- 员工表 CREATE TABLE emp ( id INT PRIMARY KEY AUTO_INCREMENT, name VARCHAR(20) NOT NULL, age INT DEFAULT 20, salary DECIMAL(10,2), dept_id INT, manager_id INT ); INSERT INTO dept(name) VALUES ('技术部'), ('市场部'), ('人事部'); INSERT INTO emp(name, age, salary, dept_id, manager_id) VALUES ('张三', 24, 8000, 1, NULL), ('李四', 28, 12000, 1, 1), ('王五', 30, 9500, 2, 1), ('赵六', 26, 6500, 2, 2), ('孙七', 32, 15000, NULL, 2);

练习题目就按 4.3 里提的那几类来,写完再去 Navicat 或命令行里核对结果。我强烈建议重点练习“查每个部门的平均工资”和“查工资高于平均工资的员工”,这两题涉及聚合、分组、子查询、JOIN 四个知识点,一次次通过它们能检验本章的掌握程度。

5.2 常见报错与排查思路

复习过程中一定会遇到报错,我把常见的几种整理成速查:

现象可能原因排查方向
ERROR 2002 Can't connect through socketMySQL 服务未启动或 socket 路径不对本地连接不要带 -h 参数,先确认服务状态
外键插入失败关联父表没有对应记录先查父表主键是否存在,再查外键字段值
WHERE 中使用别名报错SQL 执行顺序问题把 WHERE 条件改成原始列名,或移到 HAVING
Navicat 连本机 MySQL 报 SSL 错误SSL 配置不匹配连接属性的高级选项里关闭 SSL 要求
字段无法设置默认值为 0旧表结构未修改用 ALTER TABLE 语句显式设置默认值

热搜词里有一个“mysql 设置默认值为 0”和一个“mysql ssl 连接错误”,这些问题其实都是复习时容易碰上的,别觉得是自己笨,环境问题才是最常见的学习拦路虎。报错时先从服务和权限两个维度排查,再去看语法和配置,顺序不能乱。

5.3 值得继续扩展的内容

第三、四章复习完,如果还有余力,建议往这几个方向扩展,都是黑马课程之后的内容,也是热搜词里高频出现的方向:

  • 常用函数:比如 STR_TO_DATE 把字符串转日期,DATE_FORMAT 把日期格式化成字符串,处理报表时几乎天天用。
  • 存储过程和触发器:理解“封装一段 SQL 逻辑”和“自动触发执行”两种能力,能更好地理解业务代码与数据库的边界。
  • 连接池:为什么程序不能每次查数据库都重新建连接?因为建立连接的开销远高于复用连接,HikariCP、Druid 这类连接池就是解决这个问题的。
  • 主从复制与远程表同步:如果要把远程数据库的某张表同步到本地,最简单的方式是 mysqldump 导出再导入,适合一次性同步;需要持续同步则考虑主从复制。这个场景在维护多套环境时非常常见。

这些内容不要求现在全学会,但心里要有个概念,等学 JavaWeb、Spring 的时候连接池和事务管理会再次出现。

5.4 工具与环境准备建议

复习阶段不需要一上来就装什么重型工具。MySQL 官方社区版加一个可视化客户端就够,客户端可以用开源免费的 DBeaver,也可以用 Navicat Lite 或者 DataGrip,按自己的习惯来就行。安装时注意字符集选择 utf8mb4,这个是老生常谈但确实最常见的中文乱码根源。

我自己复习时的习惯是命令行和可视化工具混用:学习语法用命令行,能明显感受到 SQL 语句的原始形态;核对数据和查表结构用可视化工具,效率高。视频课里讲到查询优化、看执行计划时,一定要自己在客户端里打开 EXPLAIN 看一下结果,只有自己跑过一次,才能把“索引命中”这个抽象概念转化为具体的 rows 扫描行数下降。

复习完这两章,我最大的体会

如果把 MySQL 学习比作学开车,前两章是认识方向盘、油门和刹车,第三、四章就是真正上路:会看路况、会变道、会处理突发状况。我自己复习下来最强烈的感受是,这两章的内容绝对不能只看不练,尤其是 JOIN、子查询、事务隔离级别、联合索引这四块,每一块都必须有自己的“操作记忆”。

最后分享一个亲测有效的小技巧:复习完当天,把当天学的 SQL 关键字和概念用自己的话在手机上备忘录里整理一遍。这种“输出式复习”比再看一遍视频有效得多。等到面试前,翻备忘录比翻整本笔记快太多了。保持这个习惯,你的 MySQL 基础会扎得比大多数人牢。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/30 3:35:15

数据库三级模式:逻辑与物理分离的架构核心

1. 为什么数据库设计绕不开“三级模式”做数据库相关的工作,不管你是后端开发、DBA、架构师,还是刚入门的学生,大概率都听过“三级模式”这个词。刚接触时我也觉得这不过是一套理论概念,考试背完就忘。但真正在项目里踩过坑之后才…

作者头像 李华
网站建设 2026/9/30 3:35:14

debug_zero.cpp解析:深入HotSpot虚拟机与Zero解释器

说实话,第一次看到"Gemini永久会员 关于 debug_zero.cpp 在 HotSpot 虚拟机中的分析"这个标题时,我第一反应是标题党。前四个字属于典型的薅羊毛话题,后面又突然跳到 JDK 源码,完全不在一个频道上。但最近我恰好正在整理…

作者头像 李华
网站建设 2026/9/30 3:35:13

SQL Server窗口函数实战:用PARTITION BY实现考场自动排考与监考编排

期中考试前一周,教务处把一份1200人的考生名单塞过来:40个考场、每场30人,要求同班学生尽量打散,最后还要打印每考场的座次表和门贴。前两年我用Excel处理,又是筛选又是随机数,运气不好还要手动搬人。今年我…

作者头像 李华
网站建设 2026/9/30 3:34:59

Anaconda虚拟环境+PyCharm配置全指南

1. 为什么必须用 Anaconda 创建虚拟环境,再配 PyCharm?——这不是“多此一举”,而是开发底线你是不是也经历过:刚装好 PyCharm,新建项目跑个import pandas就报错ModuleNotFoundError;或者在公司电脑上装了 …

作者头像 李华
网站建设 2026/9/30 3:34:58

阿基米德AOA优化随机森林RF分类算法调参实战

做了几年分类算法相关的项目,我对随机森林一直是又爱又恨。爱的是它上手快、抗过拟合能力强,几乎不需要做太多数据预处理就能跑出一个还不错的baseline;恨的是它那几个超参数一旦想认真调起来,组合爆炸的速度比双十一购物车还快。…

作者头像 李华
网站建设 2026/9/30 3:34:37

AI辅助画时序图,Visual Paradigm在电商系统中的应用实战

做电商系统的这几年,我发现自己画得最多的一张图不是架构图,而是时序图。需求评审要看它、接口设计要看它、跨团队对齐还要看它。Visual Paradigm 是我一直在用的建模工具,最近它的AI辅助画时序图功能成熟了不少,实测下来能在需求…

作者头像 李华