📖 第三章 · 数据库系统
数据库系统
涵盖关系代数、键与完整性、范式理论、事务ACID、并发控制、SQL优化、NoSQL选型及数据库设计全过程。本章约占7%-13%,案例分析中数据库设计也是重点。
8知识模块
7%-13%分值占比
40+核心知识点
★★★★重要程度
关系代数
计算题高频🔢基本运算
| 运算 | 符号 | 说明 | 类型 |
|---|---|---|---|
| 选择(Selection) | σ | 按条件筛选行(元组),结果结构与原关系相同 | 一元 |
| 投影(Projection) | π | 选择指定列(属性),自动去重 | 一元 |
| 并(Union) | ∪ | 两个关系的元组合并,要求同构(属性相同) | 集合 |
| 差(Difference) | - | 在R中但不在S中的元组,要求同构 | 集合 |
| 笛卡尔积 | × | R的每个元组与S的每个元组组合,结果列数=两表列数之和 | 集合 |
🔗连接运算
| 类型 | 说明 | 示例 |
|---|---|---|
| θ连接 | 按任意条件连接(>、<、=、≥等) | R ⋈(A>B) S |
| 等值连接 | θ连接的特例,条件为"=" | R ⋈(A=B) S |
| 自然连接 | 等值连接+去重(相同属性名自动匹配,结果中相同属性只保留一列) | R ⋈ S(自动匹配同名列) |
| 外连接 | 保留未匹配元组。左外连接(保留左表)、右外连接(保留右表)、全外连接(都保留) | R ⟕ S / R ⟖ S / R ⟗ S |
| 半连接 | R中能与S匹配的元组,结果只包含R的属性 | R ⋉ S |
➗除运算
定义:R ÷ S 返回R中那些在S的所有元组上都有对应组合的元组。即"找出R中包含了S中所有情况的X值"
理解口诀:"谁全有"——R÷S的结果是:在R中与S的每一个元组都有配对的那些属性值
运算优先级:括号 > 投影/选择 > 连接/除 > 并/差 > 笛卡尔积。实际做题时从左到右,括号优先
自然连接 vs 等值连接:自然连接自动匹配同名列且结果中去重(同名列只出现一次);等值连接需要显式指定条件,结果中包含两个匹配列。考试常给两个关系表,要求计算自然连接后的元组数量和列数。
键与完整性
概念题🗝️键的层次关系
超键(Super Key):能唯一标识元组的属性集(可能包含多余属性)。范围最大
候选键(Candidate Key):最小超键,不含多余属性。一个关系可以有多个候选键
主键(Primary Key):从候选键中选定一个作为主键。唯一且非空
外键(Foreign Key):引用另一关系主键的属性。用于建立表间联系,实现参照完整性
主属性:包含在任一候选键中的属性。非主属性则不包含在任何候选键中
🛡️完整性约束
| 类型 | 含义 | 规则 |
|---|---|---|
| 实体完整性 | 主键约束 | 主键属性不能为空(NOT NULL)且值唯一 |
| 参照完整性 | 外键约束 | 外键要么为空,要么引用被参照表中存在的主键值 |
| 用户定义完整性 | 业务规则约束 | 由用户定义的约束条件,如CHECK、UNIQUE、DEFAULT等 |
包含关系:候选键 ⊂ 超键(候选键是最小超键);主键 ∈ 候选键(主键是候选键之一)。一个表只能有一个主键,但可以有多个候选键。
键的层次关系图
超键(Super Key)— 能唯一标识元组的最大集合
候选键(Candidate Key)— 最小超键,不含多余属性
主键(Primary Key)— 从候选键中选定的一个
外键(Foreign Key)— 引用另一关系的主键
包含关系:超键 ⊃ 候选键 ⊃ 主键
函数依赖与范式
★★★★★📐函数依赖
完全函数依赖:X→Y,且X的任何真子集都不能决定Y。记作 X →(f) Y
部分函数依赖:X→Y,但X的某个真子集也能决定Y
传递函数依赖:X→Y,Y→Z,且Y不→X,则X→Z是传递依赖
多值依赖:X→→Y,X的值决定Y的一组值,与Z无关
📊范式判断流程
| 范式 | 判断条件 | 消除的问题 |
|---|---|---|
| 1NF | 所有属性都是原子的(不可再分) | 属性的原子性 |
| 2NF | 在1NF基础上,非主属性完全函数依赖于候选键(无部分依赖) | 部分函数依赖 |
| 3NF | 在2NF基础上,非主属性不传递依赖于候选键(无传递依赖) | 传递函数依赖 |
| BCNF | 在3NF基础上,每个决定因素都包含候选键 | 主属性对候选键的部分/传递依赖 |
⚡反范式化
定义:为提高查询性能,有意引入冗余,降低范式级别
适用场景:读多写少、查询涉及多表JOIN、数据仓库/OLAP场景
代价:空间换时间,需要额外维护数据一致性
范式判断步骤:①找候选键 ②检查是否有非主属性对候选键的部分依赖→若有则不到2NF ③检查是否有非主属性的传递依赖→若有则不到3NF ④检查是否所有决定因素都包含候选键→若有不包含则不到BCNF。BCNF是3NF的增强,BCNF一定满足3NF,反之不然。
范式升级流程图
1NF
属性原子
属性原子
2NF
消除部分依赖
消除部分依赖
3NF
消除传递依赖
消除传递依赖
BCNF
决定因素含候选键
决定因素含候选键
升级方向:消除冗余 → 消除异常|BCNF ⊆ 3NF ⊆ 2NF ⊆ 1NF
事务与ACID
高频🔷ACID四特性
原子性(Atomicity):事务是原子操作单元,要么全部执行成功,要么全部不执行。由Undo Log实现
一致性(Consistency):事务执行前后数据库保持一致状态(约束不被破坏)。是最终目标
隔离性(Isolation):并发事务之间互不干扰。由锁机制和MVCC实现
持久性(Durability):事务一旦提交,结果永久保存。由Redo Log实现
🔀隔离级别与并发问题
| 隔离级别 | 脏读 | 不可重复读 | 幻读 | 性能 |
|---|---|---|---|---|
| 读未提交(Read Uncommitted) | 可能 | 可能 | 可能 | 最高 |
| 读已提交(Read Committed) | 防止 | 可能 | 可能 | 高 |
| 可重复读(Repeatable Read) | 防止 | 防止 | 可能(MySQL InnoDB防止) | 中 |
| 串行化(Serializable) | 防止 | 防止 | 防止 | 最低 |
📖并发问题详解
脏读:读取了另一个事务未提交的数据。对方回滚后读到的是脏数据
不可重复读:同一事务内两次读取同一行数据,结果不一致(其他事务修改并提交)
幻读:同一事务内两次执行相同查询,返回的行数不同(其他事务插入/删除)
记忆口诀:"脏不可幻"——脏读最容易发生(读未提交),幻读最难防(需串行化)。MySQL InnoDB默认隔离级别是"可重复读",通过MVCC解决了大部分幻读问题。Oracle默认是"读已提交"。
隔离级别与并发问题关系图
| 隔离级别 | 脏读 | 不可重复读 | 幻读 | 性能 |
|---|---|---|---|---|
| 读未提交 | ✗ 可能 | ✗ 可能 | ✗ 可能 | 最高 |
| 读已提交 | ✓ 防止 | ✗ 可能 | ✗ 可能 | 高 |
| 可重复读 | ✓ 防止 | ✓ 防止 | △ MySQL防 | 中 |
| 串行化 | ✓ 防止 | ✓ 防止 | ✓ 防止 | 最低 |
一致性 ↑ —— 并发性能 ↓
并发控制
常考🔐封锁协议
| 锁类型 | 符号 | 兼容性 | 说明 |
|---|---|---|---|
| 共享锁(读锁) | S锁 | S与S兼容,S与X互斥 | 允许多个事务同时读,但不允许写 |
| 排他锁(写锁) | X锁 | X与任何锁互斥 | 只允许一个事务读写,排斥其他所有锁 |
📋三级封锁协议
| 级别 | 读操作 | 写操作 | 解决的问题 |
|---|---|---|---|
| 一级封锁协议 | 不强制加锁 | 修改前加X锁,事务结束释放 | 防止丢失修改 |
| 二级封锁协议 | 读前加S锁,读完立即释放 | 同一级 | +防止脏读 |
| 三级封锁协议 | 读前加S锁,事务结束释放 | 同一级 | +防止不可重复读 |
🔑两阶段锁协议(2PL)
扩展阶段(Growing):只能获取锁,不能释放锁
收缩阶段(Shrinking):只能释放锁,不能获取锁
保证:2PL保证可串行化调度,但不保证无死锁
📑MVCC(多版本并发控制)
核心思想:数据有多份历史版本,读操作读取快照版本,写操作创建新版本
实现方式:每行数据记录创建版本号和删除版本号。读操作选择合适版本的数据
优点:读不加锁,读写不冲突,大大提高并发性能
典型应用:MySQL InnoDB、PostgreSQL
易混淆:一级→二级→三级封锁协议,级别越高加锁范围越大(读锁从"不强制"到"读完即放"到"事务结束放")。解决的问题也是递进的:丢失修改→脏读→不可重复读。注意"丢失修改"是两个事务同时修改同一数据,后一个覆盖了前一个。
SQL优化
实战重点🌳索引类型与B+树
B+树索引:最常用的索引结构。非叶子节点只存索引,叶子节点存数据且有序链表连接。范围查询高效
哈希索引:等值查询O(1),不支持范围查询和排序
聚簇索引:数据与索引存储在一起(InnoDB主键),一个表只能有一个
非聚簇索引:索引与数据分开存储,叶子节点存主键值(回表查询)
覆盖索引:查询的列全部在索引中,无需回表
复合索引:多列联合索引。遵循最左前缀原则(MySQL)
📝查询优化原则
避免 SELECT *:只查询需要的列,减少网络传输和内存消耗
合理使用索引:WHERE条件列加索引;避免在索引列上使用函数/表达式(会导致索引失效)
减少子查询:用JOIN替代子查询,优化器更容易优化
使用 EXPLAIN:分析SQL执行计划,查看是否使用了索引、扫描类型
批量操作:批量INSERT比逐条INSERT快很多
分页优化:大数据量LIMIT分页时,用延迟关联(先通过索引找到主键再回表)
📊分库分表策略
| 策略 | 方式 | 适用场景 | 挑战 |
|---|---|---|---|
| 水平拆分 | 按行拆分(同一表结构,不同数据) | 数据量大、单表行数过多 | 跨分片查询、JOIN困难 |
| 垂直拆分 | 按列拆分(按业务模块分表) | 表字段多、访问频率差异大 | 跨表JOIN、事务管理 |
| 读写分离 | 主库写+从库读 | 读多写少场景 | 主从延迟、数据一致性 |
⚠️缓存三大问题
| 问题 | 描述 | 解决方案 |
|---|---|---|
| 缓存穿透 | 查询不存在的数据(缓存和数据库都没有) | 布隆过滤器、缓存空值(短过期时间) |
| 缓存击穿 | 热点Key集中过期,大量请求打到数据库 | 互斥锁(SETNX)、永不过期(逻辑过期) |
| 缓存雪崩 | 大量Key同时过期或缓存服务宕机 | 随机过期时间、多级缓存、限流降级 |
索引失效场景:①索引列参与计算 ②索引列使用函数 ③LIKE '%xxx'(前导通配符) ④OR条件中有列无索引 ⑤复合索引不满足最左前缀 ⑤类型转换(字符串没加引号)
NoSQL数据库
常考🗃️四大NoSQL类型
| 类型 | 代表产品 | 数据模型 | 优势 | 典型场景 |
|---|---|---|---|---|
| 键值存储 | Redis、Memcached | Key-Value对 | 极高的读写性能 | 缓存、会话、计数器 |
| 文档存储 | MongoDB、CouchDB | JSON/BSON文档 | 灵活Schema、嵌套查询 | 内容管理、日志存储 |
| 列族存储 | HBase、Cassandra | 宽列(动态列) | 海量写入、稀疏数据高效 | 时序数据、大数据分析 |
| 图数据库 | Neo4j、JanusGraph | 节点+边(图结构) | 关系查询高效 | 社交网络、知识图谱、推荐 |
⚖️CAP定理与BASE理论
CAP定理:分布式系统最多同时满足三个中的两个——一致性(C)、可用性(A)、分区容错性(P)。网络分区必然存在,所以只能在C和A间选择
CP型:牺牲可用性保一致性。如Zookeeper、HBase、etcd
AP型:牺牲一致性保可用性。如Cassandra、DynamoDB、Eureka
BASE理论:BA(基本可用)+ S(软状态)+ E(最终一致性)。是AP的延伸,适合大规模分布式系统
选型对比:关系型DB强调ACID、严格一致性、结构化数据;NoSQL强调BASE、最终一致性、灵活Schema、水平扩展。实际架构中常结合使用——关系型做核心交易,NoSQL做缓存/分析/日志。
数据库设计过程
案例分析常考🔄设计四阶段
需求分析阶段:收集数据需求、处理需求。输出:数据字典(DD)、数据流图(DFD)。明确"需要什么数据"
概念结构设计:E-R模型(实体-联系图)。实体(矩形)、属性(椭圆)、联系(菱形,标注1:1/1:N/M:N)。独立于具体DBMS
逻辑结构设计:E-R图→关系模式。应用范式理论规范化。确定表结构、键、约束。与具体DBMS相关
物理结构设计:选择存储结构(堆/有序/聚簇)、存取方法(索引)、确定文件组织方式。关注性能优化
🔄ER图转关系模式规则
| 联系类型 | 转换规则 | 示例 |
|---|---|---|
| 1:1 | 可以合并到任一端的关系中,将另一端主键+联系属性作为外键加入 | 部门-经理(1:1),合并到部门表加经理ID |
| 1:N | 在N端加入1端的主键作为外键,联系的属性也放在N端 | 部门-员工(1:N),员工表加部门ID |
| M:N | 必须转换为独立的关系,包含两端主键+联系属性,主键为两端主键组合 | 学生-课程(M:N),独立选课表(学号,课程号,成绩) |
| 多元联系 | 三个及以上实体间的联系,转为独立关系,包含各实体主键 | 供应商-项目-零件(M:N:P) |
📊数据库设计注意事项
命名规范:表名用名词复数、字段名清晰明确、避免保留字
数据类型选择:能用小类型就不用大类型(TINYINT vs INT),字符串用VARCHAR而非CHAR(可变长度)
主键策略:自增ID(简单有序)vs UUID(分布式友好但无序)vs Snowflake(分布式有序)
审计字段:created_at、updated_at、deleted_at(软删除)
案例分析常考:给出ER图,要求转换为关系模式,指出主键和外键。M:N联系必须单独建表!1:N联系在外键放在N端。注意检查是否满足3NF,是否需要拆分。
章节练习
自测📝 本章练习题正在加载...