Day 5:架构、并发与高级 SQL 进阶

攻克三级模式、封锁协议、故障恢复与下午题 SQL 核心大 Boss

1. 三级模式与两级映像

“数据库分三层,是为了修改底层时不影响上层,实现数据的独立性。”

两级映像关系:

1. 外模式/模式映像:对应逻辑独立性(表结构变,视图可不变)。

2. 模式/内模式映像:对应物理独立性(存盘变,表结构可不变)。

2. 并发控制:三道防线与两段锁

“并发核心:识别三大异常,匹配封锁级别。”

并发三大异常:

  1. 丢失修改:两人同时改,后者的覆盖了先前的。
  2. 读脏数据:读到了别人最终回滚掉的假数据。
  3. 不可重复读:事务内两次读,结果因别人修改而不同。
真题演练 1

题:事务 T1 修改余额还没提交,T2 读取了。随后 T1 因故回滚(ROLLBACK)。T2 读到的是?

答案:读脏数据。
解析:只要出现了“未提交即读取”且伴随“回滚”,这就是典型的脏读。

封锁协议等级:

2PL 两段锁协议

核心:事务分为“加锁阶段”和“解锁阶段”。一旦开始解锁,绝不能再申请新锁。

3. 故障恢复:REDO 与 UNDO

“断电抢救逻辑:看日志里是否有 COMMIT 标记。”

UNDO (撤销)

日志中 没有 COMMIT。说明任务夭折,必须回滚数据。

REDO (重做)

日志中 已有 COMMIT。说明任务已成,确保存盘生效。

4. 下午题 SQL 实战知识体系

“软考下午题的 SQL 查询通常由这五种核心逻辑组合而成,掌握套路比死记硬背更重要。”

套路一:聚合统计与分组过滤 (Group By)

逻辑: 只要使用了 SUM/AVG 等聚合函数,非计算字段必须进入 GROUP BY;对汇总后的结果筛选必须用 HAVING

-- 查询购买过“家电”的客户名及总购买量,并降序排列
SELECT c.CustName, SUM(o.Qty) AS Total
FROM Orders o
JOIN Customers c ON o.CustID = c.CustID
JOIN Products p ON o.ProductID = p.ProductID
WHERE p.Category = '家电' -- 聚合前的初筛
GROUP BY c.CustName
ORDER BY Total DESC;

套路二:否定型查询 (排除法逻辑)

逻辑: 面对“从来没有”、“不曾购买”这类条件,先用子查询抓出“做过的人”组成黑名单,再用 NOT IN 剔除。

-- 查询从来没有购买过单价超过 5000 元产品的客户
SELECT CustID, CustName FROM Customers
WHERE CustID NOT IN (
    SELECT o.CustID FROM Orders o
    JOIN Products p ON p.ProductID = o.ProductID
    WHERE p.Price > 5000
);

套路三:查漏补缺 (LEFT JOIN 匹配法)

逻辑: 利用左连接保留左表全量的特性。右表(订单表)匹配不上的客户,其关联字段必定是 NULL

-- 查询已注册但没有任何订单记录的客户名
SELECT c.CustName FROM Customers c
LEFT JOIN Orders o ON c.CustID = o.CustID
WHERE o.OrderID IS NULL;

套路四:标量子查询对比 (组对比全局)

逻辑: 当需要将各组的数据(如班级平均分)与全局数据(如全校总平均分)对比时,在 HAVING 后面嵌套一个只返回单值的子查询。

-- 查询平均分超过“全校总平均分”的班级号
SELECT 班级号 FROM Scores
GROUP BY 班级号
HAVING AVG(分数) > (SELECT AVG(分数) FROM Scores);

套路五:自连接查询 (自己跟自己比)

逻辑: 同一张表起两个别名(如 e 代表员工,m 代表经理),通过连接条件建立逻辑关联。

-- 查询工资比其直接经理还要高的员工名
SELECT e.EmpName FROM Employee e, Employee m
WHERE e.ManagerID = m.EmpID AND e.Salary > m.Salary;
🚨 考场避坑准则:
1. NULL 判定:严禁写 = NULL,必须写 IS NULL
2. 执行顺序:FROM ➔ WHERE ➔ GROUP BY ➔ HAVING ➔ SELECT ➔ ORDER BY。
3. 别名使用:在 WHERE 里不能直接引用 SELECT 定义的别名(因为顺序太靠前)。