MySQL 学习进度总笔记
版本:2026-10-10
用途:记录 MySQL 学习进度,供以后新建 ChatGPT 聊天时恢复学习状态。
============================================================
一、给新聊天助手的指令
===========
我正在系统学习 MySQL。请根据这份笔记继续教学,不要从第一课重新开始。
请严格遵守以下教学要求:
-
使用中文讲解,尽量结合实际 SQL 示例和实际开发场景。
-
每一课应包含:
* 知识点讲解
* SQL 语法和示例
* 实际开发用途
* 练习题
-
练习题必须逐题进行,一次只出一道题。
-
等我回答后,再批改当前题目,不要提前公布后续题目的答案。
-
每道题按 10 分制评分,并解释:
* 本题得分
* 我的答案是否正确
* 正确答案
* 为什么正确
* 我的答案错在哪里
* 其他选项为什么错误
-
每次批改后更新本课累计成绩,并记录错题和薄弱点。
-
每课结束时总结:
* 本课知识点
* 本课总成绩
* 已掌握的内容
* 需要复习的内容
* 下一课学习计划
-
如果我答错了某道题,后续应适当安排针对性复习题。
-
不要因为某个知识点曾经答对,就直接认定我已经完全掌握;应结合多道题的表现判断。
-
涉及真实数据库的 INSERT、UPDATE、DELETE、DDL 和事务操作时,提醒我先核对实际表结构、数据及影响范围,不要直接在生产库执行未经确认的修改。
-
如果我已经回答了当前题目,请直接批改,不要重新提问。
-
如果本笔记与当前聊天中的最新学习记录冲突,以当前聊天中更新的记录为准。
-
请持续帮助我记录学习进度,让我以后可以通过这份笔记继续学习。
============================================================
二、整体学习进度
========
当前学习位置:
第11课《事务隔离级别与并发问题》已完成第一轮练习。
第11课成绩:
80 / 100 分。
下一步建议:
-
复习第11课第3题和第5题。
-
做3至5道第11课综合巩固题,一次只做一道。
-
巩固后进入第12课《数据库表设计与规范化》。
已经完成或学习过的课程:
第1课至第5课:
已完成,当前记录未保留每课详细成绩。
第6课:JOIN 多表查询
成绩:100分。
第7课:子查询
成绩:100分。
第8课:索引
成绩:100分。
第9课:主键、唯一约束、复合索引
已经学习基础内容。
早期部分练习记录为60/100。
需要继续巩固复合索引的最左前缀原则。
第10课:事务
已完成。
记录成绩:100/120分。
第11课:事务隔离级别与并发问题
已完成10道题。
成绩:80/100分。
说明:
第1至第5课的详细逐题成绩没有完整保留,不要猜测或伪造成绩。
============================================================
三、已经学习的基础知识
===========
- 基础查询
已经学习 MySQL 基础查询及相关操作,包括:
* SELECT 查询
* WHERE 条件筛选
* ORDER BY 排序
* LIMIT 分页
* 常见查询条件的使用
继续学习时应结合实际业务理解 SQL,而不是只背诵语法。
- JOIN 多表查询
第6课已经完成,成绩100分。
已学习多表关联查询的基础知识。
继续学习时,可以结合玩家、道具、订单等业务表练习关联查询。
- 子查询
第7课已经完成,成绩100分。
已学习子查询的相关知识。
后续可以结合 EXISTS、IN、关联查询等内容继续比较不同写法的适用场景。
- 索引
第8课已经完成,成绩100分。
已学习:
* 索引的基本作用
* 索引对查询性能的影响
* 使用 EXPLAIN 分析查询执行计划
* 根据查询条件判断索引是否可能被使用
需要注意:
有索引不代表查询一定会使用索引。
应结合 SQL 写法、数据分布、索引结构和 EXPLAIN 结果分析。
- 主键、唯一约束和复合索引
第9课已学习基础内容。
涉及:
* PRIMARY KEY
* UNIQUE
* 复合索引
* 最左前缀原则
需要重点复习最左前缀原则。
例如:
CREATE INDEX idx_level_gold
ON player(level, gold);
这个复合索引通常适合:
* WHERE level = 20
* WHERE level = 20 AND gold > 1000
但是,对于:
WHERE gold = 1000
通常不能有效利用该复合索引的最左前缀。
是否需要单独为 gold 建立索引,应结合真实查询、数据分布和 EXPLAIN 结果判断,不要无条件添加索引。
============================================================
四、第10课:事务
=========
课程状态:已完成。
记录成绩:100/120分。
一、事务基本操作
开启事务:
START TRANSACTION;
提交事务:
COMMIT;
回滚事务:
ROLLBACK;
二、事务的基本作用
事务可以把多条数据库操作组织为一个整体,以满足业务一致性要求。
例如,转移金币可能涉及:
-
扣除玩家A的金币。
-
增加玩家B的金币。
-
记录交易信息。
如果这些操作必须同时成功,就需要考虑在同一个事务中执行。
三、InnoDB 事务回滚
对于尚未提交的事务修改,可以通过 ROLLBACK 撤销。
COMMIT 则提交事务。
注意:
事务不能自动撤销已经提交的事务,也不能保证所有业务逻辑都没有错误。
四、条件更新与扣款
示例:
UPDATE player
SET gold = gold - 800
WHERE userId = 1001
AND gold >= 800;
这条 SQL 将余额判断与扣款放在同一条 UPDATE 中,可以降低并发扣款时先查询、后扣款造成的风险。
执行后应检查 affectedRows。
通常:
* affectedRows = 1:成功更新了一行。
* affectedRows = 0:没有行满足更新条件。
affectedRows 为0可能表示:
* 玩家不存在。
* 玩家余额不足。
* WHERE 中的其他条件不满足。
不能简单地认为 affectedRows = 0 就会抛出 SQL 异常。
五、SQL 异常与 affectedRows 的区别
SQL 执行失败时,通常会进入异常处理逻辑,例如 Node.js 的 try/catch。
SQL 成功执行,但没有匹配任何行时,通常不会因此自动抛出异常。
业务代码必须检查 affectedRows,并根据实际业务决定如何处理。
六、Node.js 事务处理
使用 Node.js 操作 MySQL 时,通常需要考虑:
* 开启事务
* 执行业务 SQL
* 成功后 COMMIT
* 发生错误时尝试 ROLLBACK
* finally 中释放数据库连接
* 处理连接失败、回滚失败等异常情况
七、事务与幂等性
事务和幂等性不是同一个概念。
事务主要用于保证一组数据库操作的原子性。
幂等性主要用于防止同一个业务请求重复执行产生错误结果。
例如,订单支付或发奖业务,可以考虑:
* 唯一订单号
* 数据库唯一约束
* 订单状态检查
* 重复请求识别
* 必要的事务处理
需要继续巩固:
-
affectedRows = 0 不会自动抛出异常。
-
开启事务不代表并发问题自动消失。
-
事务、并发控制和幂等性各自解决不同的问题。
============================================================
五、第11课:事务隔离级别与并发问题
==================
课程状态:第一轮练习已完成。
总成绩:80/100分。
本课主要内容:
* 四种事务隔离级别
* 脏读
* 不可重复读
* 幻读
* MVCC 与读视图
* InnoDB 默认隔离级别
* 并发扣款
* SELECT ... FOR UPDATE
* 死锁
* 设置事务隔离级别
第1题:脏读
得分:10/10。
场景:
事务A将金币从1000修改为700,但尚未提交。
事务B在 READ UNCOMMITTED 下读取到700。
随后事务A回滚。
正确概念:
脏读。
原因:
事务B读取了其他事务尚未提交的数据。
即使事务A最后回滚,事务B此前读取到未提交数据的事实仍然成立。
重点:
脏读通常与 READ UNCOMMITTED 有关。
READ COMMITTED、REPEATABLE READ 和 SERIALIZABLE 的正常一致性读不会读取其他事务尚未提交的数据。
第2题:READ COMMITTED 与不可重复读
得分:10/10。
场景:
事务A第一次查询金币,得到1000。
事务B将金币修改为700并提交。
事务A再次执行相同查询,得到700。
正确概念:
不可重复读。
原因:
READ COMMITTED 下,每次普通一致性读通常会建立新的读视图,因此同一事务的两次查询可能看到不同的已提交数据。
重点:
同一条记录的字段值前后发生变化,通常对应不可重复读。
第3题:REPEATABLE READ 与读视图
得分:0/10。
用户答案:C。
正确答案:B。
场景:
事务A使用 InnoDB 的 REPEATABLE READ 隔离级别。
第一次普通一致性 SELECT 查询到金币1000,并建立读视图。
事务B把金币修改为700并提交。
事务A再次执行相同的普通一致性 SELECT。
通常结果:
事务A第二次仍然读取到1000。
原因:
在 InnoDB 的 REPEATABLE READ 下,同一事务的普通一致性读通常复用第一次一致性读建立的读视图。
错误原因:
用户误以为 REPEATABLE READ 允许读取未提交数据。
需要记住:
REPEATABLE READ 不允许普通一致性读读取其他事务尚未提交的数据。
脏读通常与 READ UNCOMMITTED 有关。
注意:
普通一致性读与 SELECT ... FOR UPDATE 等锁定读的机制不同,不要认为事务内所有读取操作都必然返回同一个快照值。
第4题:幻读
得分:10/10。
场景:
事务A在 READ COMMITTED 下执行:
SELECT COUNT(*)
FROM player
WHERE level = 20;
第一次查询结果为5。
事务B插入一条 level = 20 的新记录并提交。
事务A再次执行相同查询,结果变成6。
正确概念:
幻读。
原因:
重复执行条件查询时,符合条件的记录集合发生变化。
三个概念的区别:
脏读:
读取了其他事务尚未提交的数据。
不可重复读:
同一条记录前后两次读取的值发生变化。
幻读:
同一个条件查询前后,符合条件的记录集合发生变化。
补充:
InnoDB 的 REPEATABLE READ 下,普通一致性读通常通过同一读视图保持快照一致性。
锁定读还涉及相应的锁机制。
第5题:InnoDB 默认隔离级别
得分:0/10。
用户答案:B,READ COMMITTED。
正确答案:C,REPEATABLE READ。
必须记住:
MySQL InnoDB 默认事务隔离级别是:
REPEATABLE READ
查看当前会话隔离级别:
SELECT @@transaction_isolation;
旧版本 MySQL 可能使用:
SELECT @@tx_isolation;
主要误区:
把 READ COMMITTED 当成 InnoDB 默认隔离级别。
第6题:并发扣款
得分:10/10。
场景:
玩家有1000金币。
两个请求几乎同时扣除800金币。
两个请求先查询余额,都看到1000,并判断余额足够。
正确答案:
如果业务只依靠先查询余额、再扣款,就可能出现并发业务错误。
推荐的条件更新方式:
UPDATE player
SET gold = gold - 800
WHERE userId = 1001
AND gold >= 800;
原因:
将余额判断和扣款操作放在同一条 UPDATE 中。
对于同一行的并发更新,InnoDB 会协调冲突更新。
第二个请求执行条件检查时,如果余额已经不足,通常不会更新成功。
执行后需要检查 affectedRows。
注意:
这只是示例。真实执行前必须核对表结构、字段类型、用户标识和业务规则。
第7题:SELECT ... FOR UPDATE
得分:10/10。
示例:
START TRANSACTION;
SELECT gold
FROM player
WHERE userId = 1001
FOR UPDATE;
正确概念:
在事务中,SELECT ... FOR UPDATE 是锁定读,通常会对匹配的索引记录加排他锁。
其他事务对冲突记录进行不兼容修改时,通常需要等待锁释放。
注意:
* FOR UPDATE 不会自动提交事务。
* 应使用合适的索引,减少不必要的锁定范围。
* 应尽快提交或回滚事务。
* 多条记录加锁时尽量统一顺序,但不能保证完全消除死锁。
第8题:死锁
得分:10/10。
场景:
事务A锁定玩家1001。
事务B锁定玩家1002。
事务A请求锁定1002,需要等待B。
事务B请求锁定1001,需要等待A。
正确概念:
死锁。
原因:
事务之间形成循环等待。
InnoDB 通常会检测死锁,并选择一个事务作为牺牲者回滚,以解除循环等待。
减少死锁的办法:
* 尽量统一加锁顺序。
* 缩短事务执行时间。
* 避免持锁时进行耗时网络请求。
* 在应用程序中妥善处理死锁异常。
* 如有必要,可有限次数地重试整个事务。
* 重试时必须注意幂等性,防止重复扣款或重复发奖。
第9题:设置当前会话隔离级别
得分:10/10。
正确答案:
SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED;
作用:
将当前会话的事务隔离级别设置为 READ COMMITTED。
查看当前会话:
SELECT @@transaction_isolation;
常见作用范围:
SET SESSION TRANSACTION ISOLATION LEVEL ...
设置当前会话的事务隔离级别。
SET GLOBAL TRANSACTION ISOLATION LEVEL ...
设置全局默认隔离级别,通常影响之后建立的会话。
需要相应权限,且不会自动改写已有会话的会话级设置。
SET TRANSACTION ISOLATION LEVEL ...
设置下一个事务的隔离级别,不等同于持续修改当前会话默认值。
第10题:REPEATABLE READ 综合判断
得分:10/10。
场景:
事务A第一次普通一致性读得到1000并建立读视图。
事务B把金币更新为700并提交。
事务A再次执行相同的普通一致性 SELECT。
正确答案:
通常仍然返回1000。
原因:
InnoDB 默认的 REPEATABLE READ 下,同一事务的普通一致性读通常复用第一次查询建立的读视图。
注意:
SELECT ... FOR UPDATE 等锁定读与普通一致性读不同。
第11课成绩统计
第1题:10/10
第2题:10/10
第3题:0/10
第4题:10/10
第5题:0/10
第6题:10/10
第7题:10/10
第8题:10/10
第9题:10/10
第10题:10/10
总分:80/100。
第11课需要重点复习的内容
-
InnoDB 默认隔离级别是 REPEATABLE READ,不是 READ COMMITTED。
-
REPEATABLE READ 下,同一事务的普通一致性读通常复用同一个读视图。
-
不要混淆普通一致性读与 SELECT ... FOR UPDATE 锁定读。
-
区分脏读、不可重复读和幻读。
-
事务不能单独保证所有并发扣款或重复请求都安全。
-
条件更新、事务、锁和幂等性需要根据业务组合使用。
============================================================
六、当前薄弱点总结
=========
薄弱点1:复合索引最左前缀原则
例如:
CREATE INDEX idx_level_gold
ON player(level, gold);
需要理解:
为什么该索引通常能支持 level 查询,但通常不能有效支持只按 gold 查询。
建议使用不同 WHERE 条件和 EXPLAIN 进行练习。
薄弱点2:事务中的 affectedRows
需要牢牢记住:
SQL 成功执行但没有更新任何行,不代表发生 SQL 异常。
affectedRows = 0 时,应结合 WHERE 条件和业务逻辑分析原因。
薄弱点3:事务与幂等性
事务不能保证同一个订单或请求只执行一次。
需要考虑唯一约束、订单状态、重复请求检查等机制。
薄弱点4:默认隔离级别
必须记住:
MySQL InnoDB 默认事务隔离级别是 REPEATABLE READ。
薄弱点5:读视图
需要继续理解:
READ COMMITTED 下每次普通一致性读通常建立新的读视图。
REPEATABLE READ 下同一事务的普通一致性读通常复用同一个读视图。
============================================================
七、下一阶段学习计划
==========
下一步先完成第11课巩固,再进入第12课。
第11课巩固建议:
出3至5道综合题,每次只出一道,覆盖:
-
READ COMMITTED 与 REPEATABLE READ 的区别。
-
InnoDB 默认隔离级别。
-
普通一致性读与 SELECT ... FOR UPDATE 的区别。
-
并发扣款与条件更新。
-
死锁与事务重试。
巩固完成后,开始:
第12课:数据库表设计与规范化
建议内容:
-
数据库表设计的基本原则。
-
主键设计与自增主键。
-
字段类型的选择。
-
字段长度、NULL、默认值和约束。
-
一对一、一对多、多对多关系。
-
第一范式、第二范式、第三范式。
-
数据冗余和数据一致性。
-
规范化与适度反规范化。
-
使用游戏服务端场景设计玩家表、道具表、订单表。
-
根据业务需求设计表结构并完成练习。
练习仍然需要逐题进行,每题按10分制批改。
============================================================
八、后续进度记录规则
==========
每完成一课,请继续更新这份笔记。
需要记录:
* 课程名称。
* 课程完成状态。
* 每道题的题目主题、用户答案、正确答案和得分。
* 本课总分。
* 已经掌握的知识点。
* 错题与错误原因。
* 仍需复习的内容。
* 下一课名称和学习起点。
不要只记录"学过某知识点",还要记录错误原因,以便后续针对性练习。
============================================================
笔记结束
====