原文筆記
本課程筆記資料庫系統 · 30 篇
Day 12 - 数据库70题:综合题 62-71
参考重点:教材第 5 章完整性,第 11 章恢复技术,第 12 章并发控制。SQL 均按 SQL Server 写法。
62. 什么是数据库的转储?转储的意义是什么?
答案:
数据库转储是把数据库复制到后援存储介质上,形成后援副本的过程。意义是在数据库遭到破坏,尤其是发生介质故障时,可用后援副本和日志文件恢复数据库。
讲解:转储是恢复的基础。静态转储简单但影响业务;动态转储允许业务运行,但必须配合日志保证一致性。
63. 为什么要建立日志文件?
答案:
日志文件记录事务对数据库的更新操作,是事务故障和系统故障恢复的依据。通过日志可以撤销未提交事务、重做已提交事务,并配合检查点提高恢复效率。
讲解:日志通常记录事务标识、操作类型、数据对象、旧值、新值等。必须遵守先写日志原则:数据页写盘前,相应日志先写入稳定存储。
64. 怎样进行系统故障的恢复?
答案:
系统故障恢复一般步骤:
- 从最近检查点开始扫描日志。
- 找出故障时已经提交但可能未完全写盘的事务,执行
REDO。 - 找出故障时尚未提交的事务,执行
UNDO。 - 恢复结束后数据库回到一致状态。
讲解:系统故障不破坏外存数据库文件,但会丢失内存缓冲区内容。因此既可能需要重做提交事务,也可能需要撤销未提交事务。
65. 怎样进行介质故障的恢复?
答案:
介质故障恢复一般步骤:
- 更换或修复故障介质。
- 装入最近一次数据库后援副本。
- 利用转储以来的日志文件,重做已经提交的事务。
- 必要时撤销未提交事务,使数据库达到一致状态。
讲解:介质故障会损坏外存数据,因此仅靠日志不够,必须先有数据库备份作为恢复起点。
66. 数据库在运行过程可能产生的故障有哪几类?
答案:
常见故障包括:
- 事务故障。
- 系统故障。
- 介质故障。
- 计算机病毒、恶意破坏或灾难性故障。
讲解:不同故障需要不同恢复策略。事务故障通常 UNDO 即可;系统故障需要 UNDO/REDO;介质故障需要备份和日志。
67. 叙述数据库的并发控制。
答案:
数据库并发控制是 DBMS 对多个事务同时访问同一数据的操作进行调度和协调,使并发执行结果等价于某个串行执行结果,从而保持数据库一致性。
常用方法:
- 封锁机制和两段锁协议。
- 时间戳排序。
- 多版本并发控制(MVCC)。
- 设置事务隔离级别。
讲解:并发控制的目标不是消灭并发,而是在高并发和正确性之间平衡。教材重点是封锁、封锁协议、可串行化和死锁处理。
68. 在数据库保护中,安全性和完整性有何区别?
答案:
- 安全性:保护数据库免受非法访问、非法使用、泄露或破坏。
- 完整性:保证数据库中的数据正确、有效、相容,符合语义约束。
例子:
- 用户没有权限查看成绩表却试图查询,这是安全性问题。
- 成绩被写成 150 分,这是完整性问题。
讲解:安全性管“谁能做”,完整性管“做出来的数据是否合法”。
69. 设数据库含 S、C、D 三个关系表,使用 SQL Server 设置各个表操作之间的完整性约束。
题面关系:
S
| 学号 | 姓名 | 班号 |
|---|---|---|
| S2 | 王华 | 98001 |
| S6 | 李英 | 98002 |
| S12 | 刘强 | 98003 |
C
| 课程号 | 课程名称 |
|---|---|
| K1 | 英语 |
| K12 | 高等数学 |
D
| 学号 | 课程号 | 分数 |
|---|---|---|
| S2 | K1 | 84 |
| S6 | K1 | 79 |
| S12 | K1 | 95 |
| S2 | K12 | 91 |
| S6 | K12 | 82 |
| S12 | K12 | 67 |
答案:
CREATE TABLE dbo.S (
学号 varchar(20) NOT NULL,
姓名 nvarchar(50) NOT NULL,
班号 varchar(20) NOT NULL,
CONSTRAINT PK_S PRIMARY KEY (学号)
);
CREATE TABLE dbo.C (
课程号 varchar(20) NOT NULL,
课程名称 nvarchar(100) NOT NULL,
CONSTRAINT PK_C PRIMARY KEY (课程号),
CONSTRAINT UQ_C_课程名称 UNIQUE (课程名称)
);
CREATE TABLE dbo.D (
学号 varchar(20) NOT NULL,
课程号 varchar(20) NOT NULL,
分数 decimal(5, 2) NULL,
CONSTRAINT PK_D PRIMARY KEY (学号, 课程号),
CONSTRAINT FK_D_S FOREIGN KEY (学号)
REFERENCES dbo.S(学号)
ON UPDATE CASCADE
ON DELETE NO ACTION,
CONSTRAINT FK_D_C FOREIGN KEY (课程号)
REFERENCES dbo.C(课程号)
ON UPDATE CASCADE
ON DELETE NO ACTION,
CONSTRAINT CK_D_分数 CHECK (分数 BETWEEN 0 AND 100)
);
讲解:
S.学号和C.课程号是实体完整性。D(学号, 课程号)是选课表组合主键,保证同一学生同一课程只有一条成绩。D.学号、D.课程号是外键,保证参照完整性。CHECK保证用户定义完整性。ON DELETE NO ACTION表示有选课记录时不能随便删除学生或课程;如果业务要求删除学生时同步删除成绩,可改成ON DELETE CASCADE。
70. 设有三个事务 T1、T2 和 T3,动作分别为:T1: A=A+2,T2: A=A*2,T3: A=A**2。假定这三个事务允许并行操作,讨论它们可能实施的调度。
答案:
若要求正确并发,调度结果应等价于某个串行调度。设初值为 A=a,三个事务的 6 种串行顺序结果为:
| 串行顺序 | 最终结果 |
|---|---|
| T1 -> T2 -> T3 | ((a + 2) * 2)^2 |
| T1 -> T3 -> T2 | (a + 2)^2 * 2 |
| T2 -> T1 -> T3 | (2a + 2)^2 |
| T2 -> T3 -> T1 | (2a)^2 + 2 |
| T3 -> T1 -> T2 | (a^2 + 2) * 2 |
| T3 -> T2 -> T1 | 2a^2 + 2 |
讲解:这三个操作都读写同一数据 A,彼此不交换顺序。例如先加 2 再乘 2,与先乘 2 再加 2 结果不同。因此正确调度必须可串行化。实际系统中可让每个事务对 A 加 X 锁并保持到提交,这样并发执行会退化为某个串行顺序,但结果正确。
71. 假设存款余额 X=1000 元,甲事务取走 300 元,乙事务取走 200 元,执行时间如下。如何实现这两个事务的并发控制?
题面调度:
| 甲事务 | 时间 | 乙事务 |
|---|---|---|
| 读 X | T1 | |
| T2 | 读 X | |
| 更新 X=X-300 | T3 | |
| T4 | 更新 X=X-200 |
答案:
该调度会产生丢失修改。甲、乙都读到 X=1000,甲写回 700,乙再按旧值写回 800,最终余额可能为 800,甲的取款被覆盖;正确结果应为 500。
可用排他锁或可串行化事务控制:
-- 甲事务
BEGIN TRANSACTION;
UPDATE dbo.Accounts
SET Balance = Balance - 300
WHERE AccountNo = 'X';
COMMIT TRANSACTION;
-- 乙事务
BEGIN TRANSACTION;
UPDATE dbo.Accounts
SET Balance = Balance - 200
WHERE AccountNo = 'X';
COMMIT TRANSACTION;
若必须先读再算,可在 SQL Server 中使用更新锁和保持锁:
BEGIN TRANSACTION;
DECLARE @x decimal(12, 2);
SELECT @x = Balance
FROM dbo.Accounts WITH (UPDLOCK, HOLDLOCK)
WHERE AccountNo = 'X';
UPDATE dbo.Accounts
SET Balance = @x - 300
WHERE AccountNo = 'X';
COMMIT TRANSACTION;
讲解:UPDLOCK, HOLDLOCK 使事务在读取余额时就锁住该行,并保持到事务结束,另一个事务必须等待。这样两个取款事务按某个串行顺序执行,最终余额为 1000 - 300 - 200 = 500。