资讯详情

数据库系统工程师2010年真题错题本:关系代数除法与两段锁协议深度拆解

📅 2026/10/23 9:22:11 | 华诺云谱 👁 阅读
数据库系统工程师2010年真题错题本:关系代数除法与两段锁协议深度拆解
1. 为什么2010年的数据库真题值得单独建一个错题本很多人备考数据库系统工程师时习惯把历年真题从最近年份往前刷2010年这套卷子往往被排到很后面甚至有人觉得太老了参考价值不大直接跳过。我一开始也是这么想的直到有一次模拟测试我在关系代数除法和两段锁协议这两个知识点上连续翻车回头一查这两类题在2010年上半年的卷子里出现过至少三道而且考法相当刁钻。从那以后我就专门给2010年这套题建了一个独立的错题本原因很简单这一年的命题风格处在一个转折点上既保留了早期偏重理论推导的特点又开始大量引入实际工程场景的判断类题目这种混搭风格恰恰是现在考试里最容易让人失分的地方。所谓错题本不是简单把做错的题抄一遍。我见过太多人把错题本做成了抄题本题目、选项、答案一字不落抄下来结果复习的时候根本不想翻。真正有用的错题本核心是记录你当时为什么选错、正确的思考路径应该是什么、这个知识点还会以什么形式出现。对于数据库系统工程师这个科目来说2010年的题目尤其值得这样处理因为那一年的题目里有很多看起来考A其实考B的陷阱比如表面问范式分解实际考的是函数依赖闭包的计算表面问并发调度实际考的是可串行化的判定条件。这篇文章适合两类人一类是正在系统备考、想把历年真题吃透的考生另一类是有一定数据库基础、但一做题就发现知识点好像会但题就是做不对的从业者。我会以2010年这套题为样本把错题本的建立方法、典型错题的拆解思路、以及如何从一道错题反推出整个知识块的复习策略完整地讲一遍。你不需要有很深的数据库功底但需要愿意动手把每一道错题真正搞懂而不是对个答案就翻篇。2. 2010年数据库真题的命题特征与错题本定位2.1 这一年的卷子到底特殊在哪里把2010年的数据库系统工程师真题和前后几年的卷子放在一起对比会发现几个很明显的特征。第一个特征是理论题的计算量明显偏大。比如关系代数部分那一年考了一道涉及六个关系的除法运算题需要先做投影再做除法再自然连接步骤多、中间结果容易出错。第二个特征是概念辨析题开始玩文字游戏比如共享锁和排他锁的兼容矩阵题目不会直接问你兼容性而是给一个调度序列让你判断哪些锁请求会被阻塞。第三个特征是应用题开始贴近真实场景比如有一道关于数据库恢复的题给了一个检查点发生后的日志序列让你判断哪些事务需要重做、哪些需要撤销。这三个特征叠加在一起导致2010年这套卷子的平均失分率比相邻年份高出不少。我自己的统计是在关系代数、并发控制、恢复系统这三个模块上2010年的错题数量是2009年的将近两倍。这不是因为题目本身超纲而是因为命题人把多个知识点揉进了一道题里你只要有一个环节没想清楚整道题就崩了。2.2 错题本应该记录什么、不记录什么基于上面的分析我给2010年错题本定了一个原则只记录思路断点不记录知识盲区。什么意思如果一道题我做错是因为我压根不知道什么是两段锁协议那这道题不值得进错题本我应该做的是去翻教材把这个概念补上。但如果一道题我知道两段锁协议的定义却在判断具体调度是否满足两段锁时出了错那这道题就必须进错题本因为我的问题不是不知道而是知道但用不对。具体来说每道错题我会记录四个字段字段内容示例题目编号年份题号2010-33错误类型概念混淆/计算失误/审题偏差/知识盲区概念混淆断点描述我当时是怎么想的卡在哪一步以为共享锁之间不兼容正确路径正确的推导过程用我自己的话写共享锁与共享锁兼容共享锁与排他锁不兼容这个表格看起来简单但关键在于**断点描述必须用你自己的话写**不能抄答案解析。因为只有用你自己的语言复述一遍你才能确认自己是真的想通了而不是看答案觉得有道理。2.3 为什么按知识模块分类比按年份分类更有效一开始我是按年份顺序整理错题的2010年的错题放在一起2009年的放在一起。复习的时候发现一个问题我翻2010年错题本时看到一道关系代数的题然后下一道是并发控制的题再下一道是范式的题思维频繁切换复习效率很低。后来我改成按知识模块分类把所有年份的错题打散重新归到关系模型SQL并发控制恢复范式设计这几个大类下面。这样复习的时候我可以集中一个下午只攻克并发控制这一类错题思维不用来回跳。对于2010年这套题我的分类是这样的关系代数与关系演算约4道错题主要集中在除法运算和元组演算的等价转换SQL与完整性约束约3道错题集中在嵌套查询和断言的使用范式与函数依赖约5道错题集中在候选码求解和保持依赖的分解并发控制约6道错题集中在两段锁、可串行化判定、锁兼容矩阵恢复系统约4道错题集中在检查点机制和日志重做/撤销的判断数据库设计与ER模型约3道错题集中在弱实体集和聚合的转换这个分布本身就说明了一个问题2010年卷子的失分重灾区在并发控制和范式设计这两个模块的错题加起来占了将近一半。如果你也在备考建议把这两个模块的复习时间至少增加30%。3. 关系代数除法那道让我卡了四十分钟的题3.1 题目长什么样为什么容易做错2010年那道关系代数除法题题干给了三个关系学生选课关系SC学号课程号成绩、课程关系C课程号课程名、还有一个临时关系R课程号。题目要求用关系代数表达式表示选修了R中全部课程的学生学号。这道题的标准答案是π学号(SC) ÷ π课程号(R)但当时我在考场上花了将近四十分钟尝试了各种连接和投影的组合就是没想到用除法。为什么容易做错因为除法的语义和日常直觉是反的。我们平时说选修了全部课程直觉上会想先找出所有课程然后看哪个学生选的课包含了这些课程这个思路会引导你去用连接或者NOT EXISTS。但关系代数除法的定义是R÷S返回的是那些与S中所有元组都有对应关系的元组。用生活化的类比来说除法就像是一个全能选手筛选器——你给出一份比赛项目清单除法帮你找出参加了清单上所有项目的选手。3.2 除法的计算步骤拆解我在错题本上把除法的计算过程拆成了四步每次遇到除法题就按这个流程走确认被除关系和除关系的属性集。被除关系R的属性集必须包含除关系S的属性集否则除法无意义。在SC÷C的例子中SC的属性是{学号课程号成绩}C的属性是{课程号}S的属性集{课程号}是R属性集的子集可以做除法。找出被除关系中不属于除关系的属性。SC中不属于C的属性是{学号成绩}但注意除法的结果只保留这些属性中能够与S中所有元组匹配的部分。这里有个容易忽略的点成绩属性虽然不在除关系中但它会影响除法的结果吗答案是不会因为除法的定义只关心属性值的存在性不关心其他属性的具体值。所以SC÷C的结果属性是{学号成绩}但同一个学号可能因为不同课程的成绩不同而出现多次需要再做一次投影去掉成绩。用象集的概念验证。对于SC中的每个学号计算它在课程号上的象集。比如学号001选修了{1,2,3}学号002选修了{1,2}学号003选修了{1,2,3,4}。如果R中的课程号是{1,2,3}那么只有001和003的象集包含了R的全部课程号所以结果是{001,003}。检查是否需要额外投影。如果被除关系中有多个非除关系属性除法结果会保留所有这些属性的组合通常需要再投影一次得到最终需要的属性。注意除法运算的优先级低于投影和选择所以在写表达式时如果先做了投影再除法要确保投影后的属性集仍然包含除关系的属性集。3.3 从这道题延伸出的复习策略这道题让我意识到关系代数不能只背定义必须动手算。我在错题本上给自己加了一条规则每遇到一道除法题必须用象集的方法手算一遍再用除法表达式写一遍两种方法结果一致才算过关。后来我发现很多教材上讲的除法可以用投影和差集来等价表达其实在考试中很少直接考等价转换更多是考你对除法语义的理解。所以复习的重点应该放在象集的计算上而不是等价表达式的推导。另外2010年这道题还有一个变种考法如果题目问的是选修了R中全部课程且成绩都及格的学生学号那除法就不够用了需要先对SC做选择成绩60再做除法。这个变种在后续年份的考试中出现过我在错题本上专门标注了除法选择的组合考法。4. 两段锁协议为什么我明明知道定义却判断错4.1 两段锁的两段到底指什么两段锁协议的定义看起来很简单事务分为两个阶段扩展阶段只能加锁不能解锁收缩阶段只能解锁不能加锁。但我在做2010年的一道调度判断题时明明记得这个定义却把一个不满足两段锁的调度判断成了满足。问题出在我对阶段的理解太死板了。那道题给的调度是这样的T1先对A加共享锁然后对B加排他锁然后释放A的共享锁然后对C加共享锁。我当时的判断是T1先加锁再加锁然后解锁然后加锁——这明显违反了解锁后不能再加锁的规则所以不满足两段锁。这个判断是对的但我卡在了另一个调度上T2先对A加共享锁然后释放A的共享锁然后对B加排他锁。我当时的想法是T2只加了一次锁就释放了然后才加第二次锁这算不算两段我犹豫了很久最后选错了。4.2 锁点与生长阶段判断两段锁的正确姿势后来我在错题本上总结了一个更直观的判断方法画一条时间轴把所有加锁操作标记为上升所有解锁操作标记为下降如果整条曲线上只有一个峰值即所有上升操作都在所有下降操作之前就满足两段锁。用这个方法重新看T2加共享锁上升释放共享锁下降加排他锁上升——曲线上有两个峰值所以不满足两段锁。这个单峰值的判断方法比死记定义好用得多因为它把抽象的阶段变成了可视化的曲线。我在错题本上把2010年所有涉及两段锁的调度题都画了一遍曲线发现了一个规律命题人特别喜欢在释放锁之后又加锁这个点上设陷阱而且往往会把释放锁的操作藏在一个看似无关的读操作后面让你忽略它其实是一个解锁动作。4.3 锁兼容矩阵的快速记忆法两段锁的判断题往往需要结合锁兼容矩阵来判断某个加锁请求是否会被阻塞。2010年有一道题给了四个事务的调度序列问哪个事务会被阻塞。要快速判断必须对锁兼容矩阵非常熟悉。我一开始是死记硬背的后来发现用读写两个字就能推导出来共享锁S锁是读锁排他锁X锁是写锁读和读兼容S-S兼容读和写不兼容S-X不兼容写和写不兼容X-X不兼容这个推导逻辑比背矩阵表更可靠因为考试时紧张容易记混但读读兼容、读写冲突、写写冲突这个原则是不会忘的。我在错题本上把2010年所有涉及锁兼容的题都重新用这个原则推了一遍确认没有遗漏。当前锁\请求锁S锁X锁S锁兼容不兼容X锁不兼容不兼容提示在判断调度是否满足两段锁时不要只看加锁和解锁的顺序还要检查是否存在锁升级的情况。比如一个事务先对A加共享锁然后想对A加排他锁这属于锁升级在扩展阶段是允许的但升级后就不能再降级。5. 检查点与日志恢复那道让我重新理解REDO和UNDO的题5.1 检查点机制的核心逻辑2010年恢复系统部分有一道题给了一个包含检查点的日志序列问系统崩溃后哪些事务需要重做、哪些需要撤销。我当时的错误在于把检查点的作用理解成了检查点之前的事务都不用管结果把一些需要重做的事务漏掉了。检查点机制的核心目的是减少恢复时需要扫描的日志量。当系统发生检查点时会把当前所有活跃事务的列表和它们最近一次日志记录的地址写入检查点记录。恢复时从检查点开始往后扫描而不是从日志开头扫描。但关键在于检查点之前已经提交的事务如果它们的修改还没有写回磁盘仍然需要重做。这一点是我当时忽略的。5.2 REDO和UNDO的判断流程我在错题本上整理了一个判断流程每次遇到恢复题就按这个流程走找到最后一个检查点记录记下检查点时刻的活跃事务列表。从检查点开始向后扫描日志直到日志末尾。对于每个事务如果日志中有COMMIT记录且COMMIT在检查点之后则该事务需要REDO。如果日志中有COMMIT记录但COMMIT在检查点之前则该事务的修改可能已经写回磁盘也可能没有需要根据具体题目条件判断。通常题目会给出检查点时所有脏页已写回的条件这时就不需要REDO。如果日志中没有COMMIT记录则该事务需要UNDO。对于UNDO的事务需要反向扫描日志把它的修改撤销掉。这个流程看起来简单但实际操作时容易在检查点之前的COMMIT这个点上出错。2010年那道题就是在这里设了陷阱有一个事务在检查点之前已经COMMIT但题目没有明确说脏页是否写回我默认它不需要REDO结果答案是需要REDO因为题目隐含了检查点时脏页未全部写回的条件。5.3 从这道题学到的审题技巧这道题让我意识到恢复系统的题目答案往往藏在题干的细节里。比如检查点发生时所有脏页已写回磁盘和检查点发生时部分脏页已写回磁盘这两种表述会导致完全不同的答案。我在错题本上专门开了一个审题陷阱栏目把这类因为漏看条件而做错的题都记下来每次复习时先看这个栏目提醒自己读题要逐字读。另外2010年还有一道关于日志先写原则的题问的是在什么情况下可以把修改写回磁盘。这个原则的核心是必须在相应的日志记录写回磁盘之后才能把数据页写回磁盘。这个原则的目的是保证即使系统崩溃也能通过日志恢复。我在错题本上把这条原则和检查点机制放在一起对比发现它们其实是同一个目标的两个方面检查点是为了减少恢复时间日志先写是为了保证可恢复性。6. 范式分解从一道题看候选码求解的通用方法6.1 候选码求解的图论方法2010年范式部分有一道题给了一个关系模式R(A,B,C,D,E)和一组函数依赖要求判断R属于第几范式。我当时的错误在于候选码求错了导致后续的范式判断全错。候选码求解是范式题的基础如果这一步错了后面全盘皆输。我在错题本上总结了一个基于函数依赖图的候选码求解方法画出函数依赖图每个属性是一个节点每个函数依赖是一条有向边。找出所有入度为0的属性这些属性必须出现在候选码中因为它们不能被其他属性推导出来。从入度为0的属性出发计算它们的闭包。如果闭包包含了所有属性则这些属性就是一个候选码。如果闭包不包含所有属性则需要从入度不为0的属性中选取一些加入直到闭包包含所有属性。检查是否有多个候选码如果有需要全部找出来。这个方法的关键在于第2步入度为0的属性必须出现在候选码中。很多人在求候选码时喜欢凭感觉试结果漏掉了一些候选码。用图论方法可以保证不遗漏。6.2 范式判断的决策树候选码求出来之后范式判断就相对机械了。我在错题本上画了一个决策树如果所有属性都是原子的不可再分则满足1NF。如果满足1NF且所有非主属性都完全依赖于候选码不存在部分依赖则满足2NF。如果满足2NF且所有非主属性都不传递依赖于候选码则满足3NF。如果满足3NF且所有决定因素都包含候选码即每个函数依赖的左部都是超码则满足BCNF。这个决策树看起来简单但实际操作时容易在部分依赖和传递依赖的判断上出错。2010年那道题就是在一个看似传递依赖的地方设了陷阱A→BB→C但B不是候选码的一部分所以A→C是传递依赖不满足3NF。我当时误以为B是候选码的一部分所以判断成了3NF。6.3 保持依赖的分解为什么有时候做不到2010年还有一道题问的是是否存在保持依赖且无损连接的BCNF分解。这道题考的是一个经典结论BCNF分解不一定能保持依赖。我当时不知道这个结论试图构造一个既保持依赖又满足BCNF的分解结果怎么都构造不出来。后来我在错题本上记下了这个结论如果要求保持依赖最高只能分解到3NF如果要求BCNF则可能丢失某些函数依赖。这个结论在考试中经常考而且往往以判断某个分解是否满足BCNF且保持依赖的形式出现。记住这个结论可以快速排除一些选项。范式是否保持依赖是否无损连接3NF可以保持可以保证BCNF不一定保持可以保证注意无损连接分解的判定方法是将分解后的关系模式两两做自然连接如果连接结果的属性集等于原关系模式的属性集则是无损连接。更正式的方法是使用Chase算法但考试中通常用自然连接的方法就足够了。7. 把错题本用出效果的几个实操心得7.1 错题本要薄不要厚我见过有人把错题本做成了厚厚一本每道错题都抄得工工整整结果复习时根本看不完。我的做法是每道错题只写三行——第一行写题目编号和错误类型第二行写断点描述第三行写正确路径。如果一道题需要写超过三行才能说清楚说明我对这个知识点的理解还不够透彻应该回去翻教材而不是在错题本上写小作文。这个三行原则的好处是复习时可以在一个小时内翻完一个模块的所有错题效率极高。而且因为写得少我会被迫提炼核心问题而不是把答案解析抄一遍。7.2 定期重做比重看更有效错题本做好之后很多人只是反复看但看和做是两回事。我的做法是每隔两周把错题本上的题目遮住答案重新做一遍。如果做对了就在题目旁边画一个勾如果做错了就画一个叉并更新断点描述。连续两次做对的题可以从错题本上移除连续两次做错的题需要重点标记并去找同类型的题目加练。这个方法的关键在于**遮住答案**。很多人复习错题时眼睛看着题目脑子里想着答案觉得自己会了但实际上并没有真正掌握。只有遮住答案重新做才能检验出真实水平。7.3 从错题反推知识框架错题本的最高级用法不是记录错题而是从错题中反推出整个知识框架的薄弱环节。比如我在2010年错题本上发现并发控制模块的错题集中在两段锁和可串行化两个点上而这两个点又都依赖于冲突可串行化这个概念。于是我回头把冲突可串行化的判定方法优先图法重新学了一遍发现之前很多错题其实都是因为优先图画错了。这种从错题反推知识框架的方法比按教材目录复习更精准因为它直接指向了你的薄弱环节。我在备考后期基本上就是拿着错题本按知识模块逐个攻克每个模块攻克的标准是该模块的错题连续两次重做都正确。7.4 2010年错题本给我的三个教训最后分享三个我从2010年错题本中得到的教训都是踩过坑之后才明白的第一个教训是不要跳过太老的真题。2010年的题目虽然年份早但命题思路和现在是一脉相承的而且因为那时候的题目更纯粹反而更适合用来打基础。第二个教训是错题本要动手写不要用电子版。我试过用笔记软件整理错题结果因为打字太快写了很多废话而且很少回头翻。后来改成手写因为写字慢被迫精简内容反而效果更好。第三个教训是错题本不是越厚越好而是越薄越好。当你的错题本从厚变薄说明你在进步如果一直很厚说明你只是在抄题没有真正消化。我现在的2010年错题本只剩下不到二十道题但这二十道题我每道都能讲清楚来龙去脉。提示如果你也在备考数据库系统工程师建议从2010年的真题开始建错题本然后逐年往后做。每做完一年就把错题按知识模块归类而不是按年份归类。这样到了考前你手里会有一个按知识模块组织的错题集复习效率比按年份翻高得多。
📝

华诺云谱内容团队

资深建站顾问 · 行业研究员

10年+企业数字化服务经验,专注智能建站、SEO优化与品牌营销,持续输出建站技巧、行业洞察与营销干货,已帮助5000+企业实现数字化增长。

你可能需要的服务

订阅华诺云谱资讯周报

每周一封,精选建站技巧、SEO与营销干货,直达邮箱。已有 8,000+ 企业主订阅,助你少走弯路。

↑