☰
中南大学数据库试题拆解:SQL、事务与索引三大考点复习指南
2026/10/13 11:25:32 网站建设 项目流程

简介:这份中南大学数据库试题资料面向高校计算机相关专业学生及数据库备考者,用于系统梳理课程重点与检验掌握程度。内容覆盖DBMS基础、三级模式结构、ER模型、关系模型与关系代数、SQL语言、索引机制、数据库保护(安全性、完整性、故障恢复、并发控制)以及关系规范化理论(1NF至3NF、函数依赖、模式分解)等核心考点,并配有选择题、填空题、术语解释与简答题等题型示例,便于对照复习与自测。资源包为1个doc文档,约164KB,结构紧凑,适合打印或电子阅读。目前已有354人学习下载,可作为期末复习、考研初试或课程巩固的参考材料,帮助读者快速定位薄弱环节,理清数据库知识脉络。

1. 数据库期末复习的“黑匣子”:从一套试题拆出三门课的核心考点

很多人拿到“中南大学数据库试题”这七个字,第一反应是去找原卷、找答案、找押题。我带过几届数据库课程的助教,也帮不少同学做过考前突击,血泪经验是:真正决定你分数的不是那套题本身,而是你能不能从题目里反推出它到底在考哪几门课的知识。数据库这门课表面是一门,实际至少横跨三门:SQL 语言与关系代数、事务与并发控制、存储与索引结构。一套期末试题的分布通常也是这个比例,SQL 占四到五成,事务与并发占两到三成,索引与物理存储占两成左右,剩下的零头是范式分解和 ER 建模。

所以这篇笔记不打算给你一份“答案”,而是把一套典型数据库试题拆成可复现的复习路径:先搞清楚每类题在考什么,再落到你能动手验证的 SQL 和参数上,最后告诉你哪些地方最容易翻车。适合正在准备数据库期末、或者想系统补一遍数据库基础的人。如果你只想要一份速查表,那这篇可能偏厚;但如果你想在考场上遇到变形题也不慌,下面的拆解方式应该对你有用。

2. 从试题反推考点分布:SQL、事务、索引各占多少分

2.1 一套典型试卷的题型与分值映射

我手里没有某一份具体的原卷,但根据常见的数据库期末命题习惯,一套 100 分试卷的题型分布大致是这样的:

题型常见分值主要考点对应章节
选择题20 分基本概念、范式判断、键的识别关系模型、范式
SQL 填空/改错25 分SELECT、JOIN、子查询、GROUP BYSQL 语言
关系代数与 SQL 互译15 分笛卡尔积、投影、选择、除法关系代数
事务与并发20 分可串行化、两段锁、隔离级别事务管理
索引与存储10 分B+ 树、哈希索引、聚簇索引物理存储
综合设计10 分ER 图转关系模式、范式分解数据库设计

这张表的意义在于:你复习时间的分配应该和分值大致成正比。很多同学把大量时间花在背范式定义上,结果 SQL 大题写不出来,直接丢掉 25 分。反过来,SQL 和事务这两块加起来 45 分,才是真正的主战场。

2.2 用 SQL 把“试题”变成可验证的练习

与其对着题目空想,不如自己建库建表,把每道题都跑一遍。下面这段 SQL 是我常用的最小练习环境,包含学生、课程、选课三张表,覆盖了试题里最常见的 JOIN 和 GROUP BY 场景:

-- 建表:学生、课程、选课 CREATE TABLE student ( sno CHAR(8) PRIMARY KEY, -- 学号 sname VARCHAR(20) NOT NULL, -- 姓名 sage INT, -- 年龄 sdept VARCHAR(20) -- 系别 ); CREATE TABLE course ( cno CHAR(4) PRIMARY KEY, -- 课程号 cname VARCHAR(30) NOT NULL, -- 课程名 credit INT -- 学分 ); CREATE TABLE sc ( sno CHAR(8), -- 学号 cno CHAR(4), -- 课程号 grade INT, -- 成绩 PRIMARY KEY (sno, cno), FOREIGN KEY (sno) REFERENCES student(sno), FOREIGN KEY (cno) REFERENCES course(cno) ); -- 插入几条测试数据 INSERT INTO student VALUES ('20240001','张三',20,'计算机'); INSERT INTO student VALUES ('20240002','李四',21,'软件工程'); INSERT INTO student VALUES ('20240003','王五',22,'计算机'); INSERT INTO course VALUES ('C001','数据库',4); INSERT INTO course VALUES ('C002','操作系统',3); INSERT INTO course VALUES ('C003','计算机网络',3); INSERT INTO sc VALUES ('20240001','C001',88); INSERT INTO sc VALUES ('20240001','C002',76); INSERT INTO sc VALUES ('20240002','C001',92); INSERT INTO sc VALUES ('20240003','C001',65); INSERT INTO sc VALUES ('20240003','C003',80);

这段代码的关键点有三个:第一,主键和外键的声明顺序会影响插入顺序,必须先插 student 和 course,再插 sc;第二,CHAR 和 VARCHAR 的选择在试题里经常考,CHAR 定长适合学号这种固定长度字段;第三,PRIMARY KEY (sno, cno) 是复合主键,这是试题里判断“候选键”的常见素材。

建好表之后,试题里最常见的几类 SQL 就能直接验证。比如“查询选修了数据库课程且成绩大于 80 的学生姓名”:

SELECT s.sname FROM student s JOIN sc ON s.sno = sc.sno JOIN course c ON sc.cno = c.cno WHERE c.cname = '数据库' AND sc.grade > 80;

这条语句考的是三表 JOIN 和 WHERE 条件的组合。很多同学在试题里写成子查询也能得分,但 JOIN 写法更直观,执行计划通常也更优。参数上唯一需要注意的是,如果 cname 有重复,结果会出现重复行,这时候要加 DISTINCT。

2.3 关系代数与 SQL 互译的固定套路

试题里关系代数题最容易让人卡住的是“除法”和“全称量词”。比如“查询选修了全部课程的学生学号”,标准解法是双重 NOT EXISTS:

SELECT sno FROM student s WHERE NOT EXISTS ( SELECT * FROM course c WHERE NOT EXISTS ( SELECT * FROM sc WHERE sc.sno = s.sno AND sc.cno = c.cno ) );

这个写法的逻辑是“不存在一门课,该学生没有选”。试题里如果考关系代数,对应的就是除法运算。我一般建议先写出 SQL,再翻译成关系代数,因为 SQL 的嵌套结构更接近人的思维。参数上要注意,内层 NOT EXISTS 的相关条件必须写全,漏掉 sc.sno = s.sno 就会变成“没有任何人选任何课”的荒谬结果。

3. 事务与并发控制:试题里最容易丢分的 20 分怎么拿

3.1 可串行化判断的三种冲突操作

事务部分的试题几乎必考“判断调度是否可串行化”。核心就是找冲突操作:两个事务对同一数据项,至少有一个是写操作,且顺序不同。下面这个调度是典型的不可串行化例子:

时间T1T2
t1读 A
t2读 A
t3写 A
t4写 A
t5读 B
t6写 B

判断方法是画优先图:T1 读 A 在 T2 写 A 之前,所以 T1 → T2;T2 写 A 在 T1 写 A 之前,所以 T2 → T1。出现环,不可串行化。试题里经常把读写顺序打乱,让你判断。我的习惯是先把所有冲突对列出来,再画箭头,最后看有没有环。这个方法比凭感觉靠谱得多。

3.2 两段锁协议与隔离级别的对应关系

试题里另一类高频题是“给定隔离级别,问允许哪些异常”。下面这张表建议直接记住:

隔离级别脏读不可重复读幻读
读未提交允许允许允许
读已提交禁止允许允许
可重复读禁止禁止允许
可串行化禁止禁止禁止

两段锁协议(2PL)保证可串行化,但可能死锁。试题里常问“为什么 2PL 不能避免死锁”,答案是因为它只要求加锁和解锁两个阶段,不要求加锁顺序。实际数据库里通常用死锁检测或超时来处理。

3.3 用 Python 模拟一个并发调度

光看表格不够直观,我一般会写一段小脚本模拟两个事务的交叉执行,观察最终结果:

# 模拟两个事务对同一账户的并发操作 balance = 1000 def t1(): global balance temp = balance # 读 temp = temp - 100 # 计算 balance = temp # 写 def t2(): global balance temp = balance # 读 temp = temp + 200 # 计算 balance = temp # 写 # 串行执行:T1 然后 T2 balance = 1000 t1(); t2() print("串行结果:", balance) # 1100 # 交叉执行:T1 读,T2 读,T1 写,T2 写 balance = 1000 temp1 = balance temp2 = balance balance = temp1 - 100 balance = temp2 + 200 print("交叉结果:", balance) # 1200,丢失了 T1 的修改

这段代码说明的是“丢失修改”问题。参数上,balance 是共享变量,temp 是本地副本。交叉执行时两个事务都基于旧值计算,后写的覆盖先写的。试题里如果问“哪种隔离级别能避免丢失修改”,答案是读已提交及以上,因为写操作会加排他锁。

4. 索引与存储:B+ 树试题的动手验证方法

4.1 B+ 树插入与分裂的手算步骤

试题里 B+ 树题通常给一个阶数 m,让你画出插入若干关键字后的树结构。以 m=3 为例,插入顺序 10, 20, 30, 40, 50:

第一步,插入 10, 20,根节点 [10, 20]。 第二步,插入 30,节点满,分裂成 [10] 和 [20, 30],根节点变为 [20]。 第三步,插入 40,进入右子节点 [20, 30, 40],满,分裂成 [20] 和 [30, 40],根节点变为 [20, 30]。 第四步,插入 50,进入右子节点 [30, 40, 50],满,分裂成 [30] 和 [40, 50],根节点变为 [20, 30, 40]。

手算的关键是记住:B+ 树的所有关键字都出现在叶子节点,内部节点只做索引。分裂时中间关键字上移到父节点。试题里经常考“插入后树的高度”,m=3 时最多三层就能存很多关键字。

4.2 聚簇索引与非聚簇索引的查询代价对比

试题里另一类题是“给定查询,问走聚簇索引还是非聚簇索引更快”。下面这张表是判断依据:

索引类型叶子节点内容范围查询回表
聚簇索引完整行数据快不需要
非聚簇索引主键值较慢需要

如果查询的列都在索引里,非聚簇索引也能很快,这叫覆盖索引。试题里如果问“为什么主键查询通常最快”,答案是因为聚簇索引的叶子节点就是数据行,一次 IO 就能拿到。

4.3 用 EXPLAIN 验证索引是否生效

建好索引后,用 EXPLAIN 看执行计划是最直接的验证方法:

-- 在 sc 表的 sno 列上建索引 CREATE INDEX idx_sc_sno ON sc(sno); -- 查看查询计划 EXPLAIN SELECT * FROM sc WHERE sno = '20240001';

输出里如果 type 是 ref 或 const,说明索引生效;如果是 ALL,说明全表扫描。参数上,EXPLAIN 的 key 列显示实际使用的索引名,rows 列是预估扫描行数。试题里如果问“什么情况下索引会失效”,常见答案是对索引列使用函数、隐式类型转换、或者 LIKE 以通配符开头。

5. 避坑与排查:数据库试题里那些反复出现的翻车点

5.1 坑一:GROUP BY 的 SELECT 列表里出现非聚合列

现象:写SELECT sno, cno, AVG(grade) FROM sc GROUP BY sno;被数据库拒绝。 原因:cno 不在 GROUP BY 里,也不是聚合函数,标准 SQL 不允许。 解决:要么把 cno 加进 GROUP BY,要么用聚合函数包起来。试题里如果考“哪条 SQL 合法”,这就是送分点。

5.2 坑二:NULL 值参与比较和聚合

现象:WHERE grade > 80查不到 grade 为 NULL 的行,COUNT(grade)比COUNT(*)少。 原因:NULL 表示未知,任何与 NULL 的比较结果都是 UNKNOWN,不是 TRUE。 解决:用 IS NULL 或 IS NOT NULL 判断,聚合时想清楚要不要算 NULL。试题里经常在选择题里埋这个点。

5.3 坑三:事务隔离级别设置后不生效

现象:设置了可重复读,但还是出现幻读。 原因:不同数据库对隔离级别的实现不同,有的默认级别就不是可重复读,有的需要重启会话。 解决:先查当前级别,再在会话级别设置。试题里如果问“哪个级别能避免幻读”,标准答案是可串行化,但实际数据库可能用间隙锁在可重复读级别就避免了。

5.4 坑四:B+ 树阶数理解错误

现象:把 m 阶 B+ 树当成每个节点最多 m 个关键字。 原因:不同教材定义不同,有的把 m 定义为子节点数上限,有的定义为关键字数上限。 解决:看题目给的例子,如果根节点有 k 个关键字,通常有 k+1 个子节点。试题里如果没明确,按“子节点数上限为 m”来算。

5.5 坑五:范式分解时丢失函数依赖

现象:把 R(A,B,C) 分解成 R1(A,B) 和 R2(B,C),但原来的 A→C 依赖丢了。 原因:只考虑了无损连接,没考虑保持依赖。 解决:分解后检查每个原依赖是否还能在某个子模式里推导出来。试题里如果问“哪个分解既无损又保持依赖”,要两个条件都验证。

6. 考前一周的复习节奏与自测方法

最后落到具体技巧上。我一般建议考前一周这样安排:第一天把 SQL 的 JOIN、GROUP BY、子查询各写十遍,直到不看答案能默写;第二天专攻事务的可串行化判断,把优先图画熟;第三天手算 B+ 树插入删除,至少画五组;第四天做两套完整模拟,掐时间;第五天只看出错的地方,把错题对应的知识点重新过一遍;第六天把范式分解和 ER 图转关系模式的固定步骤背下来;第七天不刷新题,只看自己的错题本。

自测方法上,我习惯用“三问法”:每做完一道题,问自己这题考的是哪个概念、如果题目条件变一下答案会不会变、我能不能用 SQL 或手算验证。如果三个问题都能答上来,这题才算真会。数据库试题里变形题很多,死记答案没用,理解机制才能以不变应万变。

还有一个我自己的教训:不要等到考前三天才开始看事务。事务部分的题一旦卡住,很容易在考场上慌,因为可串行化判断需要冷静画图。我当年就是先跳过事务去背范式,结果最后事务大题只写了一半。后来我改成每天先做两道事务题热身,反而越做越顺。希望帮到你。

本文还有配套的精品资源,点击获取

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询