切换日光/暗黑模式
059. SQL 基础、索引与并发更新问题
学习目标
这一节进入 MySQL 和 SQL 基础,并引出并发更新问题。
学完后,你应该能理解:
- 调试工具如何自动带 token;
- SQL 增删改查的基本形态;
- 字符串、分号和大小写规则;
- 索引为什么像目录;
explain能看出什么;- 为什么并发更新会覆盖结果。
调试工具自动认证
后端接口开启认证后,调试工具每次请求都要带 token。
可以在接口集合的上层节点设置认证方式。
认证配置会被子接口继承。
这样就不用每个接口手动复制 Authorization 请求头。
对于 JWT,可以配置:
- token 放在 header;
- 算法;
- 签名密钥;
- payload;
- 过期时间。
配置好后,调试接口会自动带上 token。
SQL 增删改查
SQL 是数据库交互语言。
常见操作包括:
insert: 新增;select: 查询;update: 更新;delete: 删除。
掌握这四类语句,就能理解大多数基础数据库操作。
批量新增
批量新增可以一次插入多条数据。
但业务上不一定总是适合批量提交。
例如用户在前端批量编辑多条记录时,可能希望能保存的先保存,不能保存的继续编辑。
这种情况下逐条提交会更灵活。
一次性数据导入更适合批量新增。
更新与删除
更新通常要带条件。
删除也通常要带条件。
例如:
sql
delete from table_name where id = '001';清空整张表是危险操作。
很多工具或项目规范会要求删除语句必须带条件,避免误删全表。
SQL 书写规则
SQL 里关键字大小写通常不敏感。
但为了可读性,团队会有自己的规范。
常见注意点:
- 语句末尾加分号;
- 字符串用单引号包起来;
- 查询字段尽量写明确字段名;
- 不要长期依赖
select *。
明确字段名能减少表结构变化带来的隐性问题。
索引像目录
索引可以理解成数据库表的目录。
没有索引时,要找某条数据,数据库可能从第一行扫到最后一行。
这叫全表扫描。
有索引时,数据库可以先查索引,再定位到对应数据行。
这会大幅提高查询速度。
索引的代价
索引不是越多越好。
索引本身也要占磁盘和内存。
当表数据新增、更新、删除时,索引也要同步维护。
所以索引要围绕真实查询场景设计。
频繁查询的条件字段适合建索引。
很少用到的字段,不一定值得建索引。
聚簇索引与非聚簇索引
聚簇索引可以把数据行和索引组织在一起。
非聚簇索引通常先通过索引找到主键,再根据主键回表查完整数据。
两者在空间占用和查询步骤上有差异。
实际选择和数据库引擎、表结构、业务查询方式有关。
索引失效
写 SQL 时要避免让索引失效。
常见情况包括:
- 对索引列做函数或运算;
- 联合索引没有按最左列开始查询;
- 模糊查询把
%放在开头; - 排序和分组字段没有合理索引支持。
索引失效后,查询可能退化成全表扫描。
用 explain 看执行计划
复杂 SQL 写完后,可以在前面加 explain。
它不会直接返回业务数据,而是返回数据库的执行计划。
重点可以先看 type 字段。
常见结果包括:
const: 常量级查询,通常很快;ref: 使用非唯一索引,通常也较好;range: 范围扫描;index: 全索引扫描;all: 全表扫描,通常要警惕。
如果看到 all,说明数据库可能扫描了整张表。
并发更新问题
后面会处理报销金额统计。
例如一个项目预算是 30 万,每通过一张报销单,就要累加已花费金额。
如果多个报销审批同时完成,就可能同时更新同一个项目的金额字段。
这就是并发更新。
账户充值案例
可以用账户充值模拟并发更新。
假设账户余额是 200。
同时发起三次充值,每次分别加 10、20、30。
预期结果应该是 260。
但如果多个请求都先读到 200,再分别写回自己的结果,最后可能只剩 230 或 240。
前面的更新被后面的更新覆盖了。
为什么前端思维不够
很多 JS 开发者习惯前端单线程模型。
但后端可能多线程、多进程、多实例部署。
同一个数据可能被多个请求同时读写。
所以后端写数据库时,要主动考虑并发更新。
尤其是字段值运算,例如金额、库存、计数器,更容易出问题。
这一节的重点
这一节先建立 MySQL 和并发更新的基础认识。
你需要记住:
- 调试工具可以在集合层设置 token;
- SQL 增删改查都要注意条件;
- 索引提高查询速度,但有维护成本;
explain可以检查执行计划;- 字段累加类更新必须考虑并发覆盖问题。