简介这份《数据库原理第四版》课件面向数据库初学者与希望系统梳理理论的专业人员覆盖从第一章绪论到第十章的核心内容重点讲解数据库系统开发流程、数据模型设计以及网状模型的实现细节。课件以数据模型为主线深入剖析概念模型、逻辑结构与物理结构并借助学生、宿舍、教师、教研室及家庭关系等实例直观展示网状模型的数据结构、数据操纵与完整性约束帮助读者理解一对多联系、码字段与DBTG系统的约束机制。资源包内含1个PPT文件压缩后约289KB以幻灯片形式呈现便于课堂演示与自学翻阅。目前已有168人学习下载适合需要夯实数据库基础、掌握网状模型建模思路并衔接后续关系模型与SQL学习的读者参考使用。1. 数据库原理第四版课件从“看得懂”到“讲得出、跑得通”的拆解路径很多人拿到《数据库原理第四版》课件的第一反应是PDF 翻一遍概念都认识可一到实验课建表、写事务、调索引就卡壳。这门课的核心不是背定义而是把关系模型、SQL、事务、并发控制、索引与查询优化串成一条能动手验证的链路。课件本身通常覆盖 ER 模型、关系代数、范式分解、SQL 语法、事务 ACID、封锁协议、日志恢复、索引结构这些模块但真正让学习者翻车的往往是“理论听得懂、实验跑不通”。这篇笔记面向三类人正在跟课但实验报告写不动的学生、需要把课件内容转成可演示案例的助教、以及想用一套最小环境复现数据库核心机制的开发者。我会按“先立概念、再搭环境、再逐模块跑通、最后排坑”的顺序把课件里最常考也最常翻车的几个点拆成可抄作业的步骤。数据库原理这门课光看课件不够得让 SQL 在终端里真的返回结果让事务在并发下真的阻塞让索引在 EXPLAIN 里真的生效。2. 把课件里的关系模型落到一张能跑的表环境、DDL 与约束验证2.1 选型理由为什么用 SQLite MySQL 双环境对照课件里的例子通常偏理论比如“学生-课程-选课”三张表但不同教材用的方言不一样。我的习惯是用 SQLite 做单机快速验证因为它零配置、文件即数据库适合验证 DDL、约束、简单事务用 MySQL 8.x 做并发和锁的验证因为 SQLite 的写锁是库级讲行锁、间隙锁会失真。两者对照能让你看清“标准 SQL”和“具体实现”的边界。安装上SQLite 直接下载可执行文件即可MySQL 建议用 Docker 起一个最小实例避免污染本机。# 启动一个 MySQL 8 容器映射到本机 3306密码设为 course123 docker run -d --name db-course \ -e MYSQL_ROOT_PASSWORDcourse123 \ -p 3306:3306 \ mysql:8.0 \ --default-authentication-pluginmysql_native_password参数说明--default-authentication-plugin是为了兼容老客户端端口映射如果本机已有 MySQL改成 3307 避免冲突。启动后用docker exec -it db-course mysql -uroot -pcourse123进入命令行。2.2 建表与约束把课件里的 ER 图翻译成 DDL课件里常见的 ER 图有实体、属性、联系落到 DDL 时要处理主键、外键、唯一约束、非空约束。以“学生-课程-选课”为例选课表的主键是联合主键外键分别指向学生和课程。很多同学在实验里只建表不加外键导致后面讲参照完整性时没有素材。-- 学生表学号为主键姓名非空年龄有检查约束 CREATE TABLE student ( sno CHAR(8) PRIMARY KEY, sname VARCHAR(20) NOT NULL, age INT CHECK (age BETWEEN 15 AND 60), dept VARCHAR(30) ); -- 课程表课程号为主键学分有默认值 CREATE TABLE course ( cno CHAR(6) PRIMARY KEY, cname VARCHAR(40) NOT NULL, credit DECIMAL(3,1) DEFAULT 2.0 ); -- 选课表联合主键两个外键成绩允许为空 CREATE TABLE sc ( sno CHAR(8), cno CHAR(6), grade DECIMAL(4,1), PRIMARY KEY (sno, cno), FOREIGN KEY (sno) REFERENCES student(sno) ON DELETE CASCADE, FOREIGN KEY (cno) REFERENCES course(cno) ON DELETE RESTRICT );逻辑说明ON DELETE CASCADE表示删除学生时自动删除其选课记录ON DELETE RESTRICT表示课程被选后不能直接删。这两个动作是课件里“参照完整性”的典型考点实验时故意删一条被引用的课程观察报错信息比背定义有效。参数上CHAR(8)和VARCHAR(20)的选择要看实际数据长度学号固定 8 位用 CHAR 更省空间姓名变长用 VARCHAR。2.3 用 INSERT SELECT 验证约束是否真的生效建完表后插入几条数据然后故意违反约束看数据库返回什么错误。这一步是很多实验报告缺失的“反向验证”。INSERT INTO student VALUES (20240001,张三,20,计算机); INSERT INTO course VALUES (C001,数据库原理,3.0); INSERT INTO sc VALUES (20240001,C001,88.5); -- 故意插入不存在的学号应报外键错误 INSERT INTO sc VALUES (99999999,C001,90); -- 故意插入超范围年龄应报 CHECK 错误 INSERT INTO student VALUES (20240002,李四,200,数学);执行后你会看到类似ERROR 1452和ERROR 3819的报错。把报错原文记进实验报告说明“约束在数据库层拦截了非法数据”这比写“约束保证了完整性”更有说服力。如果用的是 SQLite外键默认不开启需要执行PRAGMA foreign_keys ON;这是一个经典坑后面避坑章节会展开。3. 事务与并发控制在课件示例上跑出阻塞和死锁3.1 事务 ACID 的验证用 BEGIN / COMMIT / ROLLBACK 观察课件讲 ACID 时通常给一个转账例子。要验证原子性可以开两个会话一个执行转账的一半另一个查询余额看是否读到中间状态。MySQL 默认隔离级别是 REPEATABLE READSQLite 默认是 SERIALIZABLE行为不同正好用来对照。-- 会话 A BEGIN; UPDATE account SET balance balance - 100 WHERE id 1; -- 此时不提交去会话 B 查询 -- 会话 B SELECT balance FROM account WHERE id 1; -- 在 MySQL RR 下仍读到旧值逻辑说明会话 A 未提交时会话 B 在 MySQL 的 REPEATABLE READ 下读到的是快照旧值体现隔离性如果会话 A 执行ROLLBACK余额恢复体现原子性。参数上autocommit变量控制是否自动提交实验时建议显式SET autocommit 0;避免每条语句自动提交导致事务边界模糊。3.2 悲观锁与乐观锁课件里常提实验里怎么落地热搜词里出现了“数据库乐观锁、悲观锁的实现原理和适用场景”这正好是课件并发控制章节的延伸。悲观锁用SELECT ... FOR UPDATE在事务里锁住行适合写冲突高的场景乐观锁用版本号字段更新时检查版本适合读多写少。-- 悲观锁在事务中锁定行直到提交 BEGIN; SELECT * FROM account WHERE id 1 FOR UPDATE; UPDATE account SET balance balance - 100 WHERE id 1; COMMIT; -- 乐观锁表里加 version 字段 UPDATE account SET balance balance - 100, version version 1 WHERE id 1 AND version 3; -- 如果受影响行数为 0说明版本已被别人改过需要重试参数说明FOR UPDATE在 MySQL 中会加排他锁若 WHERE 条件没有索引可能升级为表锁这是实验里最容易翻车的地方。乐观锁的version字段建议用 INT每次更新自增应用层判断affected_rows决定是否重试。适用场景上悲观锁适合库存扣减这类强一致需求乐观锁适合文章点赞这类允许重试的场景。3.3 死锁复现两个会话互相等锁课件讲死锁时往往只给定义实际复现一次印象更深。开两个会话按相反顺序更新两行。-- 会话 A BEGIN; UPDATE account SET balance balance - 10 WHERE id 1; -- 不提交去会话 B -- 会话 B BEGIN; UPDATE account SET balance balance - 10 WHERE id 2; -- 不提交回会话 A -- 会话 A UPDATE account SET balance balance - 10 WHERE id 2; -- 阻塞 -- 会话 B UPDATE account SET balance balance - 10 WHERE id 1; -- 死锁MySQL 会回滚其中一个执行后会看到ERROR 1213: Deadlock found。把死锁日志用SHOW ENGINE INNODB STATUS导出来能看到两个事务的等待关系。这个实验的价值在于让你理解“加锁顺序一致”不是口号而是避免死锁的具体手段。4. 索引与查询优化让课件里的“理论代价”变成 EXPLAIN 里的数字4.1 B 树索引在磁盘上的直观理解课件讲 B 树时通常画图但学生很难感知“为什么索引能加速”。可以在 MySQL 里建一张十万行的表对比有无索引的查询耗时。-- 建一张测试表 CREATE TABLE big_table ( id INT PRIMARY KEY AUTO_INCREMENT, val INT, name VARCHAR(50) ); -- 插入十万行用存储过程或脚本 INSERT INTO big_table (val, name) SELECT FLOOR(RAND()*10000), CONCAT(name, FLOOR(RAND()*10000)) FROM information_schema.columns a, information_schema.columns b LIMIT 100000; -- 无索引查询 EXPLAIN SELECT * FROM big_table WHERE val 5000; -- 加索引后再看 CREATE INDEX idx_val ON big_table(val); EXPLAIN SELECT * FROM big_table WHERE val 5000;逻辑说明第一次EXPLAIN的type是ALL表示全表扫描加索引后变成refrows估算值大幅下降。参数上EXPLAIN的key列显示实际使用的索引filtered表示过滤比例。这个对比能让你在实验报告里写出“索引将扫描行数从十万降到约十行”的具体数字而不是空谈“索引提高效率”。4.2 复合索引的最左前缀课件考点实验验证复合索引(a, b, c)在查询条件包含a、a,b、a,b,c时生效跳过a直接查b不生效。这个规则背起来容易验证一次就记住。CREATE INDEX idx_abc ON big_table(val, name); -- 生效条件包含最左列 val EXPLAIN SELECT * FROM big_table WHERE val 100; -- 不生效跳过 val 直接查 name EXPLAIN SELECT * FROM big_table WHERE name name100;执行后看key列第一条显示idx_abc第二条显示NULL。注意如果查询只需要索引列可能走覆盖索引Extra显示Using index这是另一种优化点。参数上索引列顺序要根据 WHERE 和 ORDER BY 的实际使用频率定不是越多越好写多的表要控制索引数量。4.3 慢查询日志把“感觉慢”变成“证据慢”课件里讲查询优化往往停留在理论实际排查要用慢查询日志。MySQL 开启慢查询日志后超过阈值的 SQL 会被记录。SET GLOBAL slow_query_log ON; SET GLOBAL long_query_time 0.5; SET GLOBAL slow_query_log_file /var/log/mysql/slow.log; -- 执行一条没走索引的查询 SELECT * FROM big_table WHERE name name9999;然后在日志文件里能看到这条 SQL 的执行时间、扫描行数。参数说明long_query_time单位是秒实验环境设 0.5 秒即可生产环境通常设 1 到 2 秒。log_queries_not_using_indexes可以额外记录未走索引的查询但日志量会大按需开启。5. 避坑与排查课件实验里最容易翻车的五个点5.1 外键不生效现象是插入非法数据没报错现象在 SQLite 里建了外键插入不存在的学号数据库居然接受了。原因SQLite 默认关闭外键约束必须显式开启。解决每次连接后执行PRAGMA foreign_keys ON;或者在连接字符串里加参数。MySQL 的 MyISAM 引擎也不支持外键建表时要确认ENGINEInnoDB。5.2 事务没回滚现象是 ROLLBACK 后数据还在现象执行BEGIN后更新数据再ROLLBACK查询发现数据没变回去。原因很多客户端默认autocommit1BEGIN之前每条语句已经自动提交或者 DDL 语句会隐式提交。解决先SET autocommit 0;并且事务里避免混入CREATE、ALTER这类 DDL。用SELECT autocommit;确认当前值。5.3 死锁排查找不到头绪现象是应用报死锁但不知道哪两条 SQL 冲突现象MySQL 返回Deadlock found但业务代码里看不出哪两个事务互相等。原因死锁信息在 InnoDB 状态里默认不打印到错误日志。解决执行SHOW ENGINE INNODB STATUS\G看LATEST DETECTED DEADLOCK段落里面会列出两个事务持有的锁和等待的锁。把这段日志保存下来对照代码里的加锁顺序通常能定位到两个更新顺序相反的接口。5.4 索引建了没用上现象是 EXPLAIN 里 key 为 NULL现象明明建了索引查询还是全表扫描。原因可能有三种查询条件对索引列做了函数操作比如WHERE YEAR(create_time) 2024隐式类型转换比如字符串列用数字查或者复合索引跳过了最左列。解决把函数移到等号右边比如WHERE create_time 2024-01-01 AND create_time 2025-01-01用SHOW WARNINGS看优化器改写后的 SQL用EXPLAIN确认key列。5.5 隔离级别理解偏差现象是同一事务里两次查询结果不同现象在 REPEATABLE READ 下同一个事务里两次SELECT结果不一致。原因第一次查询后别人提交了修改而你的快照没有更新或者你误用了READ COMMITTED。解决用SELECT transaction_isolation;确认当前隔离级别理解 MySQL 的 RR 是通过 MVCC 快照实现的但SELECT ... FOR UPDATE会读最新版本。实验时把隔离级别在READ COMMITTED和REPEATABLE READ之间切换观察同一段代码的不同输出。6. 把课件变成可演示的课程设计一个最小验证脚本与我的习惯如果你要把这套内容用于课程设计或实验答辩我建议写一个一键验证脚本把建表、插入、事务、索引、死锁复现串起来。下面是一个用 Python SQLite 的最小示例重点不是代码多漂亮而是每一步都有断言失败时能定位到具体环节。import sqlite3 conn sqlite3.connect(:memory:) conn.execute(PRAGMA foreign_keys ON;) # 关键开启外键 cur conn.cursor() # 建表 cur.executescript( CREATE TABLE student (sno TEXT PRIMARY KEY, sname TEXT NOT NULL); CREATE TABLE course (cno TEXT PRIMARY KEY, cname TEXT NOT NULL); CREATE TABLE sc ( sno TEXT, cno TEXT, grade REAL, PRIMARY KEY (sno, cno), FOREIGN KEY (sno) REFERENCES student(sno), FOREIGN KEY (cno) REFERENCES course(cno) ); ) # 插入合法数据 cur.execute(INSERT INTO student VALUES (20240001,张三)) cur.execute(INSERT INTO course VALUES (C001,数据库原理)) cur.execute(INSERT INTO sc VALUES (20240001,C001,88.5)) # 验证外键插入非法学号应抛异常 try: cur.execute(INSERT INTO sc VALUES (99999999,C001,90)) print(外键未生效需要检查 PRAGMA) except sqlite3.IntegrityError as e: print(外键生效错误信息, e) # 验证事务回滚 cur.execute(BEGIN) cur.execute(UPDATE sc SET grade 100 WHERE sno 20240001) cur.execute(ROLLBACK) cur.execute(SELECT grade FROM sc WHERE sno 20240001) print(回滚后成绩, cur.fetchone()[0]) # 应为 88.5 conn.close()逻辑说明PRAGMA foreign_keys ON必须在建表前执行executescript会隐式提交所以事务验证放在后面单独做ROLLBACK后查询确认数据恢复。参数上SQLite 的内存数据库适合快速验证换成文件数据库只需把:memory:改成路径。这个脚本可以直接放进实验报告作为“可复现证据”。进阶一点你可以把 MySQL 的死锁复现也脚本化用两个线程模拟两个会话捕获Deadlock异常后打印SHOW ENGINE INNODB STATUS。这样答辩时不用现场手敲两个终端演示更稳。我自己的习惯是每学完课件一章就写一个最小验证脚本脚本里必须有至少一个“故意失败”的用例。数据库原理这门课失败用例比成功用例更能帮你记住边界。希望帮到你。本文还有配套的精品资源点击获取
阅读完成 · 觉得有帮助?