ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

数据库系统概论课后题怎么刷?关系代数、范式与并发控制全攻略

数据库系统概论课后题怎么刷?关系代数、范式与并发控制全攻略 “数据库系统概论第五版课后习题答案王珊”——说实话每一年都有无数学生搜这个关键词但真正的问题从来不是“找不到答案”而是“抄了答案还是不会做题”。这本书的课后题尤其是关系代数、范式判断、并发调度这几块出得相当有水平它考的从来不是记忆而是你是否真的理解了数据库底层那套“形式化”的思维。这篇东西不打算给你一份现成的习题答案那没有意义我想跟你聊的是面对这本书的课后题应该建立怎样一套完整的分析框架以及那些“看完答案觉得自己懂了合上书又不会”的题到底卡在哪里。我见过太多人反复刷这本书的课后题最后考试还是栽跟头。核心原因只有一个——把习题当成了“验证答案对不对”的工具而不是“搭建数据库思维模型”的训练场。下面这些内容是我自己啃这本书、带人复习、以及反复琢磨这些题背后出题意图后总结出的方法论。1. 王珊版《数据库系统概论》课后题到底在考什么1.1 为什么“看书全会、做题全废”很多同学看这本教材的时候最大的感受是概念能看懂例子能跟上一到课后题就完全没思路。这个现象几乎成了数据库课程的“群体性创伤”。问题不在你在于这本书的叙述逻辑和习题逻辑之间有一道隐形的鸿沟。教材正文为了可读性用了大量自然语言去描述概念比如“关系模型的数据结构是二维表”“事务具有ACID特性”这些描述用日常语言理解起来很轻松但课后题逼着你在形式化层面上操作这些概念。你脑子里存的是“二维表”这幅图题目问的却是关系代数表达式、函数依赖闭包、冲突等价判断。这不是知识没学懂而是大脑没有建立从“概念描述”到“形式化表达”的转换通道。举个最典型的例子学完第二章“关系代数”你对选择、投影、连接、除运算的定义背得滚瓜烂熟但做习题时看到“查询选修了全部课程的学生学号”十有八九第一反应是尝试用IN或COUNT去凑。但关系代数里根本没有“计数后比较相等”这种表达方式这里的正解是除运算。这个转换过程靠背定义是练不出来的只能靠大量在具体题目里反复摩擦。所以做这本书的课后题时第一原则是把“我记住了定义”切换成“我知道这道题在逼我用哪个定义”。一旦视角切换后面的路就好走多了。1.2 习题答案的正确打开方式“答案”这两字真是害了一批人。很多同学拿到习题解析之后第一反应是对着答案往上抄抄完觉得今天任务完成了。这种学习方法应付期末可能勉强及格但到了复试、面试或者实际项目里会被问得原形毕露。我的建议是答案应该当“裁判”而不是当“老师”。一道题卡住20分钟以上允许自己看答案看完之后在草稿纸上独立重做一遍做不出来再回头看直到能完整地不借助任何提示写出来为止。这比你把一整章的答案从头抄到尾有效五个数量级。更进一步你要给每个题记一个“卡点标签”。比如“11题卡在除法运算的语义理解”“23题卡在候选码的L/R类属性判断”。做完一整章之后把卡点标签一归类你会发现自己的薄弱点非常集中。大多数人卡来卡去就是那几个模型除运算、闭包、冲突可串行性。精准打击这些点比盲目刷一百道题有用得多。一句话这本书的课后答案是“用来发现自己哪里不懂”的不是“用来假装自己懂”的。2. 关系代数与SQL把“查数据”翻译成形式化表达2.1 关系代数题的固定拆解流程关系代数题占了第二章课后习题的大头也是很多人最初开始怀疑自己智商的地方。实际上关系代数题的解题套路非常固定就四步第一步看结果列。题目问“查询什么”查询出来的结果包含哪些属性这就是最外层的π投影。很多同学做错不是后面的连接出错而是最后投影时多投影了一个属性或少投影了一个属性。把结果列写在草稿纸最右边时刻提醒自己最终要输出的形状。第二步找数据来源。结果中的属性来自哪些关系这些关系怎么连。这决定了你的s自然连接或×笛卡尔积怎么写。自然连接会自动消除重复列做题时能少写不少条件但要注意参与连接的两个属性的事实上是同一个东西。如果两个关系没有公共列就老老实实用笛卡尔积然后写等值条件。第三步过滤行。把题目中所有的限定条件拆成语义片段对应到一个个σ选择条件。这里常见的坑是把条件的位置写错——应该先选择再连接还是先连接再选择在关系代数里结果一样但表达式长度和可读性差很多。通常先选择、再投影、最后连接能缩小中间结果规模。第四步处理“全部”“至少”类语义。这个是最核心的难点。关系代数里“查全”只有一种表达方式——除运算÷。“查询至少选修了95001号学生选修的全部课程的学生”用除法“查询选修了全部课程的学生”也用除法。这里的关键是要理解被除数、除数、商的关系被除数是“学号×课程号”的全部选课记录除数是“指定范围内的课程集合”商就是满足条件的学生。2.2 SQL题里三个最容易丢分的细节SQL题相比关系代数表达自由度更高很多人觉得简单但丢分点往往非常细。我见过太多人在第三张卷子上栽在这三个细节上细节一GROUP BY之后SELECT后面能出现什么。标准规定分组查询的SELECT子句只能出现分组属性、聚合函数、或由分组属性决定的表达式。比如SELECT Sno, COUNT(*) FROM SC GROUP BY Sno是对的但SELECT Sno, Sname, COUNT(*) FROM SC GROUP BY Sno直接报错除非Sname被包含在GROUP BY里或者数据库实现了功能依赖检测。这是个概念题的高频考点也是上机题里最常见的报错原因。细节二HAVING与WHERE的执行顺序。WHERE在GROUP BY之前过滤元组HAVING在GROUP BY之后过滤分组。这道题考察的本质是“分组前过滤和分组后过滤语义完全不同”。比如“查询平均成绩大于90分的学生的学号”必须用HAVING AVG(Grade) 90不能用WHERE AVG(Grade) 90因为WHERE不能包含聚合函数。而“查询成绩大于90分的学生的学号”就必须用WHERE因为这是对元组的过滤不是对分组的过滤。细节三EXISTS与IN的选择。“查全部”类的题目SQL的标准正解是NOT EXISTS的双重否定。很多人不理解为什么要套两层这里给你一个直观的理解查“选修了全部课程的学生”就是查“不存在这样一门课程这个学生没有选修”。所以外层查询学生内层相关子查询“是否存在一门课该学生没选”用NOT EXISTS包裹。搞清楚这个逻辑链条SQL里最难的“全称量词”题就通了。2.3 一个综合检索题的完整推导示例光说框架容易空我拿一道非常典型的题来走一遍完整推导。这道题在很多学校的期中期末里都换皮出现过设学生表S(Sno, Sname, Ssex, Sage)课程表C(Cno, Cname)选课表SC(Sno, Cno, Grade)。求检索至少选修了“数据库”和“操作系统”两门课程的学生姓名。这类题高手和普通学生的差别只在怎么翻译“二门课程”这个条件。看到“至少两门指定课程”第一反应可以是集合语义先查出这两门课各自的选课学生然后取交集。SQL可以写成SELECT Sname FROM S WHERE Sno IN (SELECT Sno FROM SC WHERE Cno ( SELECT Cno FROM C WHERE Cname 数据库)) AND Sno IN (SELECT Sno FROM SC WHERE Cno ( SELECT Cno FROM C WHERE Cname 操作系统));这个写法完全对而且好理解。但要注意如果题目把“至少两门”变成“全部”那上面的写法就不可行了因为列课程名你不知道到底几门。所以标准的“全称”写法是NOT EXISTS双层嵌套SELECT Sname FROM S WHERE NOT EXISTS ( SELECT 1 FROM C WHERE Cname IN (数据库, 操作系统) AND NOT EXISTS ( SELECT 1 FROM SC WHERE SC.Sno S.Sno AND SC.Cno C.Cno ) );这里外层NOT EXISTS对应“不存在这样一门课程”内层NOT EXISTS对应“这个学生没选这门课”。两个“不存在”叠加意思就是“所有课程这个学生都选了”。这个结构是SQL里最经典的全称量词实现务必掌握到能默写的程度。3. 范式理论判断与分解的通用方法论3.1 闭包计算是范式题的地基第六章关系数据理论是整本书的“劝退章”但也是出题人最喜欢动手脚的地方。很多同学栽在范式题上的根源不是不会判断而是不会算候选码因为候选码的确认是判断所有范式的前提。求候选码的标准工具是属性闭包算法很简单给定函数依赖集F和属性集X初始化X X然后反复扫描F中的每个依赖Y→Z如果Y ⊆ X就把Z合并进X直到X不再变大。这个过程你必须亲手在草稿纸上至少走过二十遍才会有肌肉记忆。为了快速定位候选码教材里给了一套非常实用的分类法把一个关系里的所有属性分成四类——只出现在函数依赖左侧的L类、只出现在右侧的R类、两边都出现的LR类、两边都不出现的N类。候选码一定包含所有L类和N类属性一定不包含R类属性。所以一般在草稿纸上先写X L∪N然后算X如果等于全集那X就是一个候选码如果不等于再尝试把LR类的属性逐个或组合加进X算闭包看能不能成为候选码。这个过程本质上是个搜索问题考试里通常不会让你搜索太多次比较常见的设定是L∪N算完闭包刚好就是全集直接得到唯一候选码。3.2 范式级别的判断顺序判断一个关系模式属于第几范式很多同学记了一堆定义仍然容易乱。我建议你把它当成一个递进的筛选过程检查1NF所有属性是否不可再分。这一条基本送分偶尔会来个“地址省份城市街道”这种骚操作把它拆了就完事。找候选码和非主属性用闭包算出所有候选码候选码之外的属性是非主属性这一步做错后面全错。检查2NF是否存在“非主属性对候选码的部分函数依赖”。关键点是“部分”——候选码是联合码时如果有非主属性只依赖联合码中的一部分那就不满足2NF。检查3NF是否存在“非主属性对候选码的传递函数依赖”。这里经典的例子是(学号 → 系号系号 → 系主任名)学号是主码系主任名通过系号传递依赖学号所以不满足3NF。检查BCNF对F中每一个非平凡函数依赖X→YX是否都是超码。这一步不再区分主属性非主属性只要依赖左侧不含候选码直接判死。很多人混淆3NF和BCNF的区别觉得3NF已经够了为什么还要BCNF。这个区别在“主属性对码的依赖”上3NF允许主属性部分依赖或传递依赖候选码BCNF一律不允许。考试里最经典的BCNF反例是(仓库ID物品ID管理员ID)依赖关系是(仓库ID物品ID) → 管理员ID管理员ID → 仓库ID即管理员只管理一个仓库但这个关系的主属性仓库ID被非主属性管理员ID决定它满足3NF但不是BCNF。3.3 分解到3NF/BCNF时怎么取舍范式判断题的后半段通常会让你“把不符合范式的关系模式分解为符合范式”。这里有两个完全不同的目标考试时务必看清楚题目问的是哪一个无损连接的分解分解后能通过自然连接还原出原信息。判断无损连接用表格法Chase算法在草稿纸上画行列矩阵按函数依赖不断填a最后看有没有一行全是a有就是无损。保持函数依赖的分解分解后的所有函数依赖并集等价于原来的函数依赖集。这个用不到太多算法主要是检查有没有函数依赖的左右两边属性被拆到不同的关系里。教材上给了个非常有价值的结论总能做到3NF且无损且保持依赖但BCNF只保证无损不保证保持依赖。所以题目如果要求“3NF且无损且保持函数依赖”按合成法走一遍先求正则覆盖再按每个函数依赖分组没有包含候选码的分组就单独加一个含候选码的关系。题目如果要求“BCNF且无损”就往死里拆每次找一个违反BCNF的依赖把X和X能决定的属性拆出去循环直到全满足。这里我必须强调一个实操心得考试里正在计算分解结果是否无损时优先用表格法而不要凭直觉。因为人的直觉在这种地方特别不可靠。我当年考试就栽过一次——两个分解方法凭感觉号称“显然无损”结果用表格法一验证直接翻车。4. 事务、并发与恢复简答与设计题背后的原理4.1 事务ACID和习题怎么对应事务这一章的课后题类型非常多样有的考概念辨析有的考日志恢复有的考并发调度。很多人容易把这些题当成“背诵题”处理但实际上它们本质上都是“应用题”。比如“事务的原子性由什么机制保证持久性由什么机制保证”这种高频简答题跟数据库系统内部的日志结构是强相关的。原子性和持久性主要靠日志——在事务提交前把对数据库的所有修改记录到日志中崩溃后根据日志内容UNDO没提交的事务、REDO已提交的事务。隔离性靠并发控制机制一致性是应用层的逻辑约束加上其他三个特性的配合结果。如果只是背答案日期一长就忘了理解了日志、锁和崩溃恢复这套闭环任何时候被问到都能现场推出来。这一章还经常考类似这样的题“数据库在运行过程中突然断电重启后系统如何保证一致性”这就是标准的系统故障恢复。你要从日志的检查点开始说找出最后一个检查点记录重做检查点之后所有已提交事务的更新撤销所有未提交事务的更新。这个流程在第十章习题里反复出现建议你把“系统故障→检查点→REDO→UNDO”这个链条刻在脑子里。4.2 两道经典并发题可串行化判断与两阶段锁并发控制的课后题里最“劝退”的是给一个并发调度序列让你判断是否冲突可串行化。判断的核心思路特别简单但极容易乱把所有事务中操作同一数据项且至少有一个是写操作的对找出来判断它们在不同事务中的执行顺序是否一致。具体操作是画出两个事务间的冲突边。假设有T1和T2如果T1的哪个操作在T2的相应操作之前执行就画一条T1 → T2的边。所有冲突对都处理完后检查这个有向图有没有环。有环就不可串行化无环则对应的拓扑序就是一个等价串行调度。做这类题最容易犯的一个错误是忽略了不同数据项之间的读写冲突。比如T1写A、T2读B看起来没冲突但如果这两个操作在调度里跨事务交叉你该检查的是T2有没有在另一数据项上也被T1卡住。建议你在题目旁边把每个事务涉及的数据项列表先写出来再做两两对比避免遗漏。另一类高频题是“用两阶段锁协议(2PL)判断某个并发执行是否可能发生”。这里的关键是认识到两阶段锁是保证冲突可串行化的充分条件。一个调度里所有事务都遵守2PL那它一定是冲突可串行化的反过来一个冲突可串行化的调度不等于一定可以由2PL产生因为2PL要求每个事务“先加锁、后解锁”这个顺序是全局限制的。习题里经常让你在某个给定的锁表序列下判断事务能否正常完成或者让你补全某事务的加锁解锁序列。还有一个我踩过的坑不要把“2PL”和“预防死锁”混为一谈。2PL解决的是可串行性死锁是另一个问题。很多同学在回答“两阶段锁怎么保证可串行化”时扯了一堆死锁预防结果一分没得。2PL的核心是每个事务分成“增长阶段”和“收缩阶段”增长阶段只能加锁不能解锁收缩阶段只能解锁不能加锁。死锁预防是靠超时、等待-死亡、伤口-等待这些协议来解决的两码事。4.3 日志恢复题从故障类型反推处理流程日志恢复的题在第十章课后题里占比很大但套路极为固定甚至可以整理成一张表。考试时先在草稿纸上写明故障类型再写对应策略基本就能拿全分。故障类型原因恢复策略事务故障运算溢出、死锁被选为牺牲品等利用日志UNDO该事务所有修改反向扫描日志对该事务的每个更新操作做逆操作系统故障断电、系统崩溃从头扫描日志重做所有已提交事务REDO撤销所有未提交事务UNDO有检查点则从检查点开始介质故障磁盘损坏装入最近的数据库备份重做备份之后的所有已提交事务日志REDO做题时有个细节特别容易送命——写日志必须先于写数据库。如果先写了数据库再写日志系统恰好在两者之间崩溃恢复系统并不知道这个修改是否已经落盘会产生数据不一致。所以日志恢复题的开头通常让你设计“某个事务执行完修改后、提交前的日志序列”牢记先写日志后写数据库这个原则即可。另外不管题目给多少条日志记录恢复时第一步永远是确定哪些事务已提交、哪些未提交。怎么确定看日志里有没有该事务的COMMIT记录。有COMMIT就REDO没有就UNDO。这个“先判断提交状态再决定动作”的顺序做任何日志恢复题都通用。我遇到过不少同学拿着日志列表一头扎进逐条恢复结果方向反了越做越乱。5. 数据库设计题从需求到ER图再到关系模式5.1 ER图画错的三种典型情况第七章数据库设计经常以设计题的形式出现在试卷最后一道大题它考察的是从一段业务描述中抽象出实体、属性和联系的能力。这部分没有绝对唯一的答案但有三类错误特别常见一旦犯了会被扣很多分错误一把“联系”画成了“实体”。比如“学生选课”这个概念很多新手会画一个叫“选课”的实体再连到学生和课程。但实际上选课是一个学生和课程之间的m:n联系它的属性是成绩。正确画法是实体学生和课程之间画一个菱形“选课”联系上挂一个属性成绩。一个判断原则是如果一个东西离开两端的实体就没法独立存在那它大概率是联系而不是实体。错误二实体与联系的度数搞错。比如仓库和供应商、零件三者之间的联系往往是三元联系你不能简单拆成三个两元联系因为在现实语义中一个供应商为某个仓库供应的零件种类可能和“供应商→零件”“仓库→零件”这种两两关系并不是等价的。教材和习题里专门有这种三元联系的处理逻辑结构设计时三元联系一般要单独转换为一个关系模式。错误三忽略联系上的属性。很多同学画出两端的实体后忘了考虑联系本身可能携带属性。比如“职工-部门”之间的联系是1:n“职工在部门工作的起始时间”就是联系上的属性。考试时题目描述里凡是跟在“在……时间”“从……起”这种词后面的名词基本都是联系的属性。把它们放在实体上反而会让关系模式冗余。5.2 转换为关系模式的硬规则ER图转关系模式第七章课后题要求你能机械执行一套规则。虽然“机械”两个字听起来很死板但考试时反而是最不容易扣分的部分因为规则非常明确每个实体转换为一个关系模式实体的属性就是关系的属性实体的码就是关系的码。1:1联系可以转换为一个独立的关系模式也可以并入任意一端实体对应的关系模式。并入时在另一端加入对方的码作为外键并把联系的属性加进来。实际操作中我更推荐“并入”方案因为单独建表反而多了一次关联查询在性能上不划算。1:n联系并入n端对应的实体关系模式。也就是在“多方”的关系里加入“一方”的码作为外键同时带上联系的属性。例如“部门-职工”的联系并入职工表加一个部门号字段这就够了。m:n联系必须转换为一个独立的关系模式两端实体的码组合成主码同时把联系自身的属性放入其中。比如“学生-课程”的选课联系生成SC(Sno, Cno, Grade)主码是(Sno, Cno)。这些规则真的没有太多可供“聪明发挥”的空间老老实实按规则套就是满分。如果你在做题时发现自己要加入额外判断才能得出结构那大概率是前面的ER图画得不够清晰回去检查。这里要特别提醒一点数据库设计题的评分是按步骤给的ER图画对了、关系模式转换对了、主码外码标对了每一部分都有分。千万不要因为时间不够就跳步。即使前面需求分析写不全ER图和关系模式也能拿大部分分数。考试是策略游戏这题性价比极高。6. 复习阶段的实操建议把课后题用出最大价值6.1 六轮刷题法学这本书尤其是要应付期末或者考研复试的我强烈推荐一个六轮刷题法。这套方法不是我发明的是我自己从复习备考中总结出来的每一轮的目的都不一样刷法也完全不同。第一轮随章精做。每学完一章当天的任务是只做这一章的课后题。这个阶段不追求速度追求的是暴露问题。每道题都要独立写不要看书不要看答案。卡住20分钟以上标记为“卡题”看一眼答案后必须合上答案重新写。第二轮错题重做。整本书过完一遍后翻出所有标记过的“卡题”重新做一遍。这一次你的目标不是做对而是归纳“我这道题当时为什么卡住”。写出每个题的卡点类型比如“关系代数除法语义不清”“候选码求取时没先标L/R/N类”“并发图有环没看出来”。把这些卡点类型汇总成一个LeetCode式的高频错题清单你就知道自己的命门在哪了。第三轮按模型刷。这一步特别关键。把课本所有课后题按“题型模型”重新分类而不是按章节。比如把“SQL全称量词题”归为一类把“范式判断分解”归为一类把“日志恢复题”归为一类。每个模型集中刷3-5道题直到你能不假思索地写出固定套路为止。你要的不是“会做这道题”而是“遇到这个模型秒反应”。数据库这门课的知识点虽然多但模型化之后其实总共不超过20个。第四轮限时模拟。挑3-5套往年的考试真题或者学校推荐的模拟题严格按考试时间作答。这一步特别推荐使用纸质试卷不要用电子版因为电子版会诱导你翻看答案。限时模拟的目的很单纯——检验前三轮的训练成果以及训练在时间压力下的心态。第五轮回补盲区。模拟完之后找出扣分最集中的知识点回归课本对应章节重新读一遍定义和例题然后专门做该章剩余没做过的课后题。这一轮是把“半懂不懂”变成“真懂”的关键。第六轮考前速览。考前一两天只看你的卡点标签清单和高频错题本不要再去从第一页翻书了。这个阶段看太多新内容反而会打乱你已经建立的框架保持“模型感”比什么都重要。6.2 关于版本差异与扩展学习最后聊一下版本。很多人搜到的是第五版但现在已经出了第六版。第六版相比第五版新增了大数据、云数据库、内存数据库、分布式数据库等内容但关系模型、SQL、范式理论、事务并发与恢复这些核心章节的习题逻辑几乎没有变化。如果你手头是第五版完全可以直接用如果是第六版那前九章、第十章、第十一章的课后题仍然可以作为靠谱的练习素材。另外这本书的课后题在“标准SQL”和“关系代数”的转换上非常适合搭配实际数据库操作来验证。我有个很土但很有效的建议每做完一道SQL题别只看答案对不对把它敲进SQLite或者MySQL里实际跑一遍再故意改错几个地方观察报错行为。理论上模糊的地方跑一遍语法错误就全都具象化“原来不写GROUP BY查所有非聚合列是真的会报错”这类经验比背十遍规范还要有用。针对考研的同学我多说一句很多学校初试专业课就是这本书的内容课后题和真题之间的重合度极高。第六版教材出来后官方配套的习题解析里新增了不少新题比老的习题集更贴近当前的考试风格建议优先使用配套的习题解析版本并且把近五年的真题知识点对应回课后题的章节号。这样复习的性价比是最高的。说到底这本教材的课后题不是用来“刷完”的是用来“想透”的。你每做完一道题都应该问自己一个问题“如果我把这道题的背景换掉换成另一个行业场景我还能用同样的方法做出来吗”想通了这个问题数据库对你就不再是期末的一门课而是一套真正能用来建模现实世界数据的思维工具。
返回列表