可靠订单与查询性能:并发、锁和索引|课后复习
本次商城补强回收
本日产物:线程物流批查、内存锁反例、真实数据库竞争与查询计划。逐项回到课堂同名章节,解释 Thread/start/join、共享状态、Lock、Queue、ThreadPoolExecutor/Future、异常与超时;MySQL 锁、固定顺序、EXPLAIN,指出本人代码中输入、状态与失败的位置。再用独立变体证明解释有效,不把讲过当会做。
| 风险 | 提前预防 | 怎样发现 | 怎样处理 | 怎样复验 |
|---|---|---|---|---|
| 锁只包扣减,检查在外面 | 把检查和更新放入同一锁范围 | 并发提交后核对成功数与余量 | 修临界区或数据库事务 | 再跑竞争,失败无残单 |
| Future 超时当成线程已结束 | 网络本身设超时,限制线程数 | 观察超时后运行状态与退出等待 | 区分等待超时和任务取消 | 失败项独立记录,其他项仍可见 |
| 内存绿灯冒充数据库锁 | 本地机制和真实依赖分栏 | 核对是否两个真实独立连接 | 在专用库执行竞争测试 | 核对一单成功、库存一致 |
自测:内存无锁 accepted=2、有锁 accepted=1,均 available=0;物流成功/404/超时分项;真实 MySQL 至多一单成功;EXPLAIN 同条件可比。下一日接口:沿用查询基线学习缓存;用批量报表区分 CPU 与 I/O。
今天学会了什么
能用有限线程池批查物流、收取逐项失败,解释共享状态和锁;能用两个真实数据库连接验证库存竞争,并比较同一查询的索引证据。
先指出普通读取与库存写入解决的问题为何不同,再画两个事务相反顺序锁商品时的等待环。
今天讲了什么(对照复习)
下面逐项对应课堂正文。先盖住右边那一栏,凭记忆回答;卡住了再翻回左边同名的小节。光说得出名字不算会,还要能讲清它会做什么、什么时候会失效。
| 课堂对应章节 | 必须能解释的机制与边界 |
|---|---|
| MVCC、行锁和死锁 | MVCC 让普通一致性读访问可见版本;Read View 判断可见性,undo log 帮助构造旧版本。RR 通常沿用首次一致性读的快照,RC 每次一致性读取新快照;不能把它套到所有更新与锁定读。 |
| MVCC、行锁和死锁;缓存之前,先验证交易与查询本身 | 两人读到同一库存不代表都可成交。事务内 SELECT … FOR UPDATE 保护待改库存,条件更新及影响行数检查防止超卖;等待后需重新检查事实,锁范围受索引、条件和隔离级别影响。 |
| 死锁怎样降低和处理 | 多商品按固定 ID 顺序加锁、缩短事务并保证查询条件合理可减少等待环;数据库可能回滚一个事务。仅对安全操作有限重试整个用例,保持原子与幂等边界,不能逐条提交或无限重试。 |
| 先别优化:让慢查询问题出现;B+Tree 的简化心智模型 | 先固定数据、查询与参数。B+Tree 缩小查找范围,但索引占空间、增加写成本;小样本快或单次耗时变化不说明生产效果。 |
| 聚簇索引和主键;二级索引与回表 | InnoDB 通常以主键组织聚簇索引,叶子保存行;二级索引包含索引列和主键,需要其他列时可能回表。命中索引不等于不再读取数据页。 |
| 联合索引与最左前缀 | 联合索引列序要服务 WHERE 与 ORDER BY;例如客户+创建时间查询使用候选组合。跳过左侧列的另一查询不能直接沿用相同结论。 |
| 用 EXPLAIN 检查候选;EXPLAIN 能说明什么 | 读 type、key、rows、Extra;rows 是估算,计划可能提示排序/临时处理。相同数据和参数比较前后计划及实际结果,用户耗时需另外实测,结果正确性优先。 |
出了问题:怎么发现、怎么修、怎么验证
只在你自己那份课程副本或专用实验数据上复验,把改之前和改之后的真实结果都留下来。
| 风险/现象 | 提前预防 | 怎样发现 | 怎样处理 | 怎样复验 |
|---|---|---|---|---|
| 先查后写仍超卖 | 库存更新在同一事务加锁并检查条件 | 两个独立连接竞争最后一件,核对成功订单数和余量 | 修锁定/条件更新和事务范围 | 恰当数量成功,库存不为负,失败无半订单 |
| 死锁后乱重试或局部提交 | 固定加锁顺序并设重试边界 | 保留数据库错误、事务与加锁顺序 | 回滚整个用例,仅安全时有限重试 | 故障后订单库存仍一致,无无限等待循环 |
| Fake 测试被当成真实锁证据 | 标明真实连接与隔离环境 | 核对连接主体和并发执行记录 | 到课程 MySQL 执行竞争实验 | 真实证据单独记录;未跑不签通过 |
| 索引越多越好或只看 key | 由实际查询设计候选 | 比较同数据同参数下 rows、Extra、结果和耗时 | 调整候选列序,重新评估写入代价 | 保留前后计划、结果一致性和多次测量条件 |
闭卷自测
先自己答一遍,再去运行或翻回课堂核对;不确定的地方标出来,别用 AI 的答案顶掉你自己的第一次判断。
-
MVCC 解决看见哪个版本,为什么仍不能保证抢最后一件不超卖?普通一致性读与锁定读如何区别?
-
两个事务相反顺序锁两件商品,怎样形成等待环?固定顺序为什么只是降低风险?
-
聚簇索引、二级索引与回表分别是什么?增加索引付出什么代价?
-
客户+创建时间索引能否让所有时间筛选都同样快?从查询条件解释。
-
EXPLAIN 的 rows 是实测行数吗?请给出一份能够支撑有限性能结论的记录清单。
-
为什么库存仍为0也可能卖出两件?Future等待超时后线程是否已经结束?怎样把失败物流与其他成功结果一起交付?
再看一眼真实业务
从真实后台筛选条件选择一条课程查询,并用自己的数据库测量。商品页的可售提示只是一条观察,不能据此认定平台是否加锁、是否采用某隔离级别。
今天留下什么,下节课怎么接着用
同时保留本人物流批查、内存竞争实验和逐项失败记录;下一日用同一执行方式判断方法比较订单报表。
保留真实双连接竞争、失败无半更新、固定加锁顺序说明、索引候选与前后 EXPLAIN、数据规模和测量条件。W03-D02 以该查询基线判断商品详情缓存是否有价值。
今天解释并验证有限场景;分库分表、分布式锁和生产级压测不因一次实验通过而视为完成。