ARTICLE DETAIL

资讯详情

深耕编程入门与网站建设的一线实战洞察。

数据库系统期末复习全攻略:关系模型、SQL与并发控制一网打尽

数据库系统期末复习全攻略:关系模型、SQL与并发控制一网打尽 学期快结束了数据库系统这门课又到了最让人头疼的时候。我自己当年在软件学院备考时也走过不少弯路。身边的同学普遍有两种极端一种是一头扎进题海各种SQL练习题刷到吐另一种是天天抱着一本教材反复看但一做题就发懵。说实话这两条路都不太适合应对数据库系统期末考试。这门课既考理解也考动手尤其看重你能不能把关系模型、SQL、规范化理论、事务并发控制这些知识串成一条线。这篇文章我把自己踩过的坑、总结过的重点和考场上的答题经验都整理出来给正在准备这门课的同学做一个参考。不管你是一路认真听课想拿高分还是考前突击只想稳妥过关这套思路都能帮你快速抓住主干。从课程性质来看数据库系统属于典型的“理论实践”结合科目。很多同学容易把它当成一门记忆类课程觉得背会几个概念就能应付但实际卷子上大量题目都要现场推导比如范式分解、关系代数表达式、并发调度正确性判断。所以我建议复习时不要只停留在“看懂”层面一定要动笔做、动手写把每一步推导都落到纸面上。文章下面的内容我会按照期末最常见的模块顺序依次展开每个模块都会给出复习重点、典型题型的答题思路以及我个人的一些避坑经验。1. 数据库系统期末复习的整体框架先想清楚这门课考什么1.1 知识地图一门课其实就是一张总图我复习到最后阶段习惯把整门课压缩成一张“总图”。数据库系统其实可以分成两大块来看一块是“数据怎么存、怎么设计”另一块是“数据怎么用、怎么保证正确”。前者对应关系模型、约束、ER图、规范化解决的是从现实世界中提取数据并合理地放入数据库的问题后者对应SQL、视图、索引、事务、并发控制和恢复解决的是用户怎么高效且安全地操作这些数据的问题。这两块之间不是孤立的。ER图设计得合理后面规范化压力就小关系数据库设计得乱复杂查询自然写起来别扭。我复习时会先画这张总图把每一章的标题往两个大方向里归位再补充具体关键词。比如“异常”这个考点在数据库设计中对应插入异常、删除异常和更新异常在并发控制中又对应丢失更新、脏读和不可重复读。如果你脑子里有这张总图就不会把这些相似的名词搞混。软件学院期末考试通常喜欢考综合性题目比如给你一个业务场景让你先画ER图再转换成关系模式接着判断范式和分解最后写SQL查询。这一条完整的链路其实就是把整本书串起来考。所以复习时千万不要零散地背最好按“设计到查询”这条主线走一遍一个完整的案例从头做到尾。1.2 复习节奏三轮复习法和时间分配建议我自己的备考节奏一般是三轮。第一轮是快速过知识点不必抠得太细重点是恢复记忆把教材目录和课堂PPT过一遍遇到不熟悉的概念标记出来。这一轮大概花两到三天不用做题。第二轮是重点突破把标记出来的难点配合习题逐个打掉并且开始动手做SQL、写关系代数、做范式分解。这一轮花的时间最长大概三到四天目标是所有常规题型都能独立完成。第三轮是模拟和查漏用往年题或自己组合的题目做一到两次完整模拟严格控制时间然后针对薄弱环节再补。时间分配上不同模块的权重差别很大。以我参加过的考试为例关系代数和SQL合起来能占三十分左右ER图和规范化大概占二十五分左右事务并发控制接近二十分其他概念题、填空题和简答题加起来占剩下的部分。所以复习顺序也可以按权重来先把SQL和关系代数拿下再投入时间搞规范化和ER图最后背熟事务与并发控制的相关概念。这种策略的好处在于前两个模块都是“会就是会”掌握了就能稳定拿分比死记硬背那些琐碎概念性价比高得多。还有一个被很多人忽略的点教材上的例题一定要亲手写一遍而不是“看一遍看懂”。数据库系统的计算题步骤非常固定比如无损连接判断有判定表法候选键求解有闭包法锁协议判断有固定的流程。如果只看不练考场上很容易出现“思路知道但具体下笔时少写一步”的情况。我见过太多同学在范式分解时漏掉检验保持函数依赖这一环节完全不是不懂就是平时没养成完整的步骤习惯。2. 关系模型、关系代数与SQL性价比最高的拿分区域2.1 关系模型和完整性约束概念题的高频来源关系模型这一章概念题几乎每年都会出现。你需要把几个基础概念说清楚关系、元组、属性、候选键、主键、外键、关系模式、关系数据库。最容易混淆的是候选键和主键之间的关系前者是能唯一标识元组的最小属性组后者是从候选键里选出来的一个一个关系可以有多个候选键但只能有一个主键。还有一个常见考点是关系的三个完整性约束实体完整性、参照完整性和用户定义完整性。实体完整性规定主属性不能为空参照完整性规定外键要么为空要么是被参照关系中实际存在的主键值用户定义完整性是根据实际业务自定义的约束比如年龄必须大于零。这些内容看似简单但考试时往往考得比较细。比如“外键是否允许为空”这道判断题就容易坑人在参照完整性中如果外键不是主属性它可以为空表示还没有对应关系但如果外键同时是主属性的一部分则受实体完整性约束不能为空。复习到这个层次就不只是背概念了而是理解了约束之间的内在关系考场上无论怎么变形都能应对。2.2 关系代数别怕“除运算”它就是一道套公式题关系代数是很多同学眼中的拦路虎尤其是除运算一看到就发懵。但我学完之后回头看关系代数其实是整门课里最“机械”的部分只要把几个基本操作理解了任何复杂查询都能按套路拆出来。基本操作包括选择、投影、连接和除法。选择和投影都是一元操作选择是选行投影是选列注意投影后要把重复元组去掉。连接主要是自然连接和等值连接自然连接会把公共属性合并等值连接不合并。这些基本操作中最容易在细节上丢分的是投影后去重和自然连接的公共属性处理。除运算之所以让很多人觉得难是因为它表达的是“全部”这种语义。比如查询“选修了全部课程的学生学号”可以用除法先算出所有学生的学号与选课情况的自然连接再除以所有课程的课程号。除法结果的每一行都表示该学生在除法子查询涉及的所有课程上都有选课记录。如果套到具体例子上设学生选课表SC包含Sno和Cno两列课程表Course包含Cno一列则答案是π_Sno, Cno(SC) ÷ π_Cno(Course)。这个式子写出来以后很多人会发现其实没那么玄乎关键是识别出“全部”“至少包含所有”这类关键字。关系代数的另一类常考题型是“查询同时满足多个条件”比如查“既选修了数据库又选修了操作系统的学生”。这种题通常有两种写法一种是先选课再自连接另一种是用除法或分组。我用下来觉得如果条件数量少直接用连接再加选择就够了如果条件数量多除法和分组会显得更清晰。考试时优先选择自己最有把握的写法不用追求形式上的高级。2.3 SQL复杂查询的高分套路SQL部分的分值一直是重头戏。基础部分考察建表、插入、删除、修改注意主键和外键的声明方式以及删除和修改语句中的WHERE条件。这部分如果丢分多半是语法细节比如忘记写关键字、字符串忘加引号、数值类型不匹配。我复习时总结了一个SQL查询的通用套路先看题目要求查什么确定SELECT后面的列再看数据来源确定FROM和JOIN接着看筛选条件确定WHERE如果需要分组聚合先写GROUP BY再写HAVING过滤组。只要按这个顺序思考多数题目都能稳稳拿下。复杂查询主要考子查询、连接、分组聚合和存在性判断。子查询分相关子查询和非相关子查询非相关子查询先执行内层再执行外层相关子查询则每处理一行外层数据都要执行一次内层。这类题目的典型例子是查询“比平均成绩高的学生名单”可以用一条子查询先算平均分再在外面比较。而“查询每个系成绩最高学生的信息”这类题则要用到相关子查询或者窗口函数考试时如果允许使用窗口函数ROW_NUMBER()配合PARTITION BY会非常简洁但有些课程大纲里没讲窗口函数那就只能用相关子查询来兜底。还有一个高频考点是EXISTS和NOT EXISTS它们通常和“全部”“不存在”语义相关。典型的用法是查询“没有选修任何课程的学生”可以写成NOT EXISTS子查询查询“选修了全部课程的学生”则可以转换为其反面即“不存在一门课程该学生没有选”。很多教材喜欢直接用除法写这类问题但SQL里用EXISTS写更容易理解而且不易出错。我个人的建议是复习时两种方法都掌握考试时根据题目给的表结构灵活选择。3. 数据库设计与规范化从ER图到范式分解3.1 ER图设计实体、属性和联系的判断技巧ER图题目在期末试卷里几乎从不缺席通常会给一段业务描述让考生画出ER图再转换成关系模式。这类题目虽然看起来自由发挥但改卷时还是有明确得分点的。第一步要分清哪些是实体哪些是属性。一个常见的判断标准是如果某个信息还需要被独立查询或关联其他信息就应该设计成实体如果只是某个实体的静态描述则设计成属性。比如“部门”和“员工”通常是两个实体而“员工的姓名”就应该做成属性不需要单独用一个实体来表示。联系的处理是ER图设计的关键。一对多联系通常在“多”端加外键多对多联系需要单独建一张联系表一对一则可以在任意一端加外键。很多同学容易忽略的是联系本身也可以有属性比如“选课”这个联系除了学生和课程两个实体的主键外它的属性“成绩”就只能放在联系上不能挂在学生或课程实体上。转换关系模式时多对多联系会生成独立的关系模式该模式的主键是两端实体的主键组合联系自带的属性也要放进这个模式中。画ER图时还有两个细节容易扣分一是实体和属性的下划线主键属性要加下划线二是联系的类型要标清楚是用一只乌鸦脚表示多端还是用一根箭头表示一端不同教材画法略有差异考试时尽量按照课程要求的画法来。我吃过一次亏平时用惯了某一种建模工具结果考试时画法与课程要求不一致阅卷老师看得费劲分数也不理想。考前一定要确认本课程的标准画法尽量保持一致。3.2 函数依赖与候选键求解掌握闭包就够了规范化部分的理论基础是函数依赖。理解函数依赖要从定义出发在关系模式R中如果属性集X的每一个取值都唯一确定属性集Y的取值就说X函数决定Y记作X→Y。这里要特别注意“充要条件”的判断比如“学号→姓名”成立但如果存在重名现象“姓名→学号”就不成立。考试常考函数依赖集的等价、最小函数依赖集和候选键求解。候选键求解是必考的一个环节最常用的方法就是属性闭包。给定一个函数依赖集F对于属性集X求X的闭包X就是不断利用F中的依赖扩展X直到不能再扩展为止。如果X包含关系模式的所有属性那么X就是超键如果X的任何一个真子集的闭包都不包含全部属性且X本身能推出全部属性X就是候选键。举一个实际例子设关系模式R(A,B,C,D)函数依赖集F{A→B, C→D}那么A{A,B}C{C,D}AC{A,B,C,D}所以AC是候选键。这种题目只要勤练习分数基本是稳拿的。除了单个候选键考试还可能考察候选键不唯一的情况。比如F{A→B, B→C, C→A}那么A、B、C各自都能推导出整个属性集所以候选键有三个。这种情况下如果要找主键就随便选一个作为主键其他候选键称为备用键。这类题目的好处是答案很客观只要过程清晰不会因为个人理解差异而失分所以性价比非常高。3.3 范式判断与模式分解规范化的完整答题步骤范式判断是期末考试的重点也是难点。1NF要求属性都是原子不可分的2NF要求在1NF基础上消除非主属性对码的部分函数依赖3NF要求在2NF基础上消除非主属性对码的传递函数依赖BCNF则更进一步要求每一个决定因素都包含码。判断范式时标准的操作流程是先求候选键再逐一检查每个非主属性是否满足对应条件。很多人容易把2NF和3NF判断混淆我建议在做题时列一张表把候选键、主属性、非主属性先写清楚再逐条判断。模式分解是高难部分。分解的目标通常有两个无损连接和保持函数依赖。无损连接判断最直观的方法是判定表法把分解后的每个关系模式作为一行属性作为列根据函数依赖不断推导并填充符号最后如果某一行全部变成a则说明分解是无损的。保持函数依赖的判断则要检查原函数依赖集中的每个依赖是否被分解后的关系模式覆盖。考试经常要求同时满足无损连接和保持函数依赖这是3NF分解可以做到的但BCNF分解可能不保持函数依赖。我见过太多同学在模式分解时只写最终答案不写过程。实际上阅卷通常是按步骤给分即使最终结果错了如果前面的判定表或中间步骤是对的也能拿到不少分。所以我强烈建议平时练习时就把每一步写规范尤其是候选键求法、闭包计算、判定表填充这三个环节每一步都标注清楚依据。考试时即使时间紧张也比把答案堆在一起碰运气要稳得多。4. 事务、并发控制与故障恢复理解原理简答题不再懵4.1 事务ACID和调度的基本概念事务是数据库系统里保证逻辑正确性的基石。事务的四个特性ACID要能完整地说清楚并且最好能用一句生活化的语言解释。原子性指事务里的操作要么全部完成要么全部不完成就像转账时扣款和入账不能只做一半一致性指事务执行前后数据库的完整性约束都不被破坏隔离性指多个事务并发执行时彼此不能被未提交的数据所干扰持久性指事务一旦提交即使系统崩溃结果也不会丢失。这四者之间联系很紧密隔离性做得越好并发性能通常越差所以数据库提供了不同隔离级别来平衡。事务调度的考点主要是判断两个并发事务的调度是否冲突可串行化。判断方法比较固定先分析事务之间每一对冲突操作然后画一个优先图如果图中存在环则不可串行化如果没有环则存在一个串行顺序等价于该调度。复习时多做几道这类题找到循环判断的手感考试时基本就是送分题。但这些题很容易在操作顺序上出错务必先把每个事务所含的读写操作一条条列出来再比较冲突关系。4.2 封锁协议与隔离级别需要形成条件反射并发控制里的封锁协议是简答题和选择题的常客。三级封锁协议的要求是递进关系一级封锁协议只要求事务在修改数据前加排他锁直到事务结束才释放它的作用是防止丢失更新二级封锁协议在事务读取数据前加共享锁读完即可释放能防止丢失更新和脏读三级封锁协议则要求事务读取数据前加共享锁事务结束后才释放能防止丢失更新、脏读和不可重复读。注意二级和三级的关键差异在于共享锁的释放时机一个是读后即放一个是事务结束才放这个区别经常被出成判断题。两阶段锁协议是保证并发调度可串行化的常用方法它要求事务分两个阶段加锁和释放锁增长阶段只加锁不放锁缩减阶段只放锁不加锁。但两阶段锁协议可能产生死锁因此数据库系统还需要死锁检测和死锁预防机制。死锁检测常采用超时法或等待图法死锁预防则通过制定加锁顺序或者一次性加锁来避免。复习这部分时建议不要只背协议条文而是针对每种现象画一个简单的例子比如用两个事务交替读写同一个数据直观体会为什么一级封锁协议能解决丢失更新却解决不了脏读。4.3 日志恢复机制REDO和UNDO怎么用故障恢复的考点主要集中在基于日志的恢复技术。日志要先写后记即先写日志文件再修改数据库这样才能在发生故障时利用日志进行恢复。恢复处理的规则可以简单记成如果日志中有事务的提交记录就对这个事务执行REDO如果日志中只有开始记录没有提交记录就对这个事务执行UNDO。这里还要注意检查点机制使用检查点可以缩短恢复时间。有了检查点后恢复时只需要考虑检查点之后尚未提交的事务和检查点之后开始执行的事物的日志记录。这类题在考试中经常给出一段日志记录序列要求判断故障后需要撤销哪些事务、重做哪些事务。做题时关键要分清楚事务状态已经提交的做REDO未提交的做UNDO。如果题目设置了检查点还需要注意检查点之前已经提交的事务不需要重新处理因为它们的改动已经写入了数据库。练习几道真题后你会发现这个模型非常固定更像一套程序化的流程而不是需要创造性的题目。5. 典型题型拆解与考场答题模板5.1 关系代数与SQL题写得规范分数才稳关系代数题如果题目没有特别要求尽量用最常规的操作符表达不要自己发明记号。书写时注意投影符号的下标、选择条件的位置以及自然连接和条件连接的区别。SQL题最怕的不是不会写而是审题不清。比如题目要“查询每个学生选课的门数”结果有人写成了“查询选课门数大于2的学生”这就是漏掉了“每个学生”的分组语义。我建议拿到SQL题先圈出几个关键词查什么、从哪查、要不要排除重复、要不要分组、分组后要不要过滤、是否要排序。把这些关键字写出来之后再动手写SQL会稳很多。对于EXISTS子查询我提供一个好用的思维模板如果要表达“所有”“全部”可以把它转换成“不存在一个反例”。例如“查询选了全部课程的学生”先想反例“存在一门课程这个学生没有选”用NOT EXISTS套进去即可。如果题目要求用关系代数写也可以用除法表达同样的语义。考试时我习惯先在草稿纸上用自然语言描述查询逻辑再翻译成符号或SQL这样能显著降低漏条件概率。5.2 范式分解题每一步都写明白范式分解题最遗憾的失分原因就是过程省略。比如题目要求把关系模式分解为3NF并保持函数依赖、无损连接。完整答题流程是第一步求候选键第二步写出函数依赖集的最小覆盖第三步按依赖集进行3NF分解第四步用合成法或判定表检验是否无损连接。每一步都要写清依据比如“某属性闭包计算如右下”不一定要写得很长但要有迹可循。我复习时把这类题的方法总结成了口诀“一求键二找依赖三分组四验无损”。分组时如果多个函数依赖左部相同可以合并成一个关系模式如果分解后没有关系模式包含候选键且分解不具有无损连接性就额外增加一个包含候选键的关系模式补上这个关系模式后分解就能保证无损连接性。这个补充步骤是高频考点一定要记牢。我在备考时做过一道经典练习题R(A,B,C,D,E)F{A→BC, CD→E, B→D, E→A}。按步骤求解后发现候选键有A和E两个分解时需要特别小心。这种综合性题目值得反复做几遍做完后把过程的每一步都对一遍答案直到自己不看答案也能完整复现为止。5.3 事务并发题优先图法是万能钥匙并发控制部分的计算题优先级图法几乎能解决所有“是否可串行化”的问题。我给大家一个分步骤的模板先把每个事务的每个操作按时间顺序编号然后找到所有冲突操作对同一数据项且至少有一个是写操作在优先图中添加有向边边的方向从先执行操作的事务指向后执行操作的事务。完成所有边的添加后对该图做拓扑排序。如果存在拓扑序列那么该调度是冲突可串行化的如果图中存在环则不是。答题时把优先图画出来再写一句结论比光写“是/否”要更有说服力也能避免阅卷老师怀疑你是猜的。对于锁协议相关的简答题可以用“几个问题、几个协议、分别解决什么”来组织答案。比如问到“为什么三级封锁协议能防止不可重复读”要先说出三级协议的具体规定再解释不可重复读产生的原因是一个事务多次读取同一数据时另一事务在两次读取之间修改了该数据而三级协议中的共享锁持续到事务结束正好阻断了这种修改发生的可能。这种“概念原因协议对应”的答题结构分数通常会比较理想。6. 常见错误与考场注意事项这些坑我都替你踩过6.1 关系代数和SQL中的低级错误清单低级错误是考试失分的大头。关系代数方面最容易犯的错误是投影后忘记去重以及自然连接和笛卡尔积混用。写SQL时常见问题包括字符串比较时忘了加单引号、子查询忘记加括号、聚合函数和GROUP BY不匹配、HAVING误写成WHERE、NULL值比较用了等号而不是IS NULL。特别是NULL很多同学以为NULL NULL成立实际上SQL里NULL的等值比较结果既不是真也不是假而是未知。查询“没有被分配系部的学生”应该写成WHERE dept IS NULL写成WHERE dept NULL查不到任何记录。分组查询中还有一个经典陷阱SELECT后面只能出现分组列和聚合函数。如果题目要求“查询每个系的最高工资”那么SELECT后写系名和MAX(salary)没问题但如果你还想显示对应员工的名字就违背了分组规则因为名字不是分组列也不是聚合结果。这类需求通常需要借助相关子查询或窗口函数来实现考试时要看清题目的表结构再决定解法。6.2 范式判断中容易混淆的概念范式判断最常见的错误是把部分依赖和传递依赖搞混。部分依赖是指非主属性依赖于候选键的一部分比如候选键是复合键(A,B)存在A→C就说明C部分依赖于候选键。传递依赖是指非主属性不直接依赖于候选键而是通过另一个非主属性间接依赖比如学号→系名系名→系主任那么在关系模式(学号,系名,系主任)中系主任就是通过系名传递依赖于学号的。判断时建议先把候选键和非主属性标出来再逐一查看每个非主属性是直接依赖于整个候选键还是依赖于候选键的一部分或是依赖于其他非主属性三种情况分别对应不同的范式等级。另外还要注意BCNF和3NF的关系。很多同学以为3NF已经是最高范式其实BCNF才是更严格的要求。BCNF要求每个非平凡函数依赖的决定因素都包含码而3NF只要求非主属性不能部分或传递依赖于码所以某些关系模式即使满足3NF由于存在主属性对另一个候选键的部分依赖或传递依赖仍然不满足BCNF。考试如果给一个满足3NF但候选键不唯一的模式很容易在BCNF判断上设坑做题时一定要把每一个函数依赖的决定因素逐一检查。6.3 考场时间分配和临场心态数据库系统期末考试题量通常不小我的经验是先做计算题和SQL题再做概念题和简答题。原因很简单计算题和SQL题只要会做基本不会因为字迹或表述问题失分而且分数占比高越做越有信心概念题和简答题即便时间紧张也可以凭印象写几个关键词拿一部分分数。我一般会在拿到试卷后花两分钟浏览整张卷子按“能做出来的优先”排序不在一道题上死磕超过十五分钟实在卡住就先跳过等后面思路开阔了再回头补。临考前一晚的复习策略也很关键我不建议这时候再刷新题而是把错题本或者平时标记的常错要点过一遍。比如连接条件写反、范式判断步骤不完整、恢复日志判断漏掉检查点这类高频失误考前看一眼能显著降低踩坑概率。还可以把前面说的“关系代数操作符表”“SQL查询关键字顺序表”“范式判断流程图”等总结性内容快速浏览一遍形成一个简洁的临考记忆包。这些内容在考场上不一定都会用上但能给你一种“我准备得很充分”的心理暗示对稳定心态好处很大。最后再分享一个小技巧也是我后来实践下来最有效的方法。复习时找一个关系比较好的同学互相给对方讲题把自己的答案用口语表达一遍。讲的过程会逼着你把知识重新组织很多你以为懂但其实模糊的地方都会暴露出来。我和同学在考前互相讲了三天最后两个人的成绩都很不错。这个方法不需要额外找资料还能加深理解建议有条件的同学都试一试。
返回列表