目录
前言:
笔记来自《文老师软考数据库》教材精讲,精讲视频在b站,某宝都可以找到,个人感觉通俗易懂。
1.1 案例分析概述
1.2 数据流图设计
2020年以后不考了
1.3 概念结构设计
- E-R图:即实体联系图,使用圆表示属性、长方形表示实体、菱形表示联系,联系两端要标注联系类型
- 联系类型:一对一:1:1、一对多:1:N、多对多:M:N。
(1)实体和弱实体(之间直接用直线连接,是从属关系,无联系类型)。
(2)多个实体一个类型(一般是三个实体连接到一个类型上,根据题目说明,若有三个实体相关则是此种情况).
(3)主键和外键(主键是本关系内唯一,外键是其他关系的主键,外键可以有多个)。
- E-R图转换为关系模式
E-R图中,有实体和联系两个概念,实体和实体之间的联系分为三种,即1:1,1:N,M:N,这三种情况转换为关系模式的方法也不同。 - 首先,每个实体都要转换为一个关系模式,对于联系:
一对一联系作为一个属性随便加入哪个实体中;一对多联系可以单独转换为一个关系模式,也可以作为一个属性加入到N端中 (N端实体包含1端的主键);
多对多,联系必须单独转换为一个关系模式(且此关系模式应该包含两端实体的主键) - 转换之后要注意:原来的两个实体之间的联系必须还存在,能够通过查询方式查到对方。
数据库设计的考法也非常固定,第一小题补充E-R图,第二小题补充关系模式,第三小题是简单的情景问答题。同样也都不难,结合题目描述和E-R图的一些特点可以轻易得出答案,技巧如下:
1、补充E-R图:这是重中之重,E-R图如果弄错了,后续题目都有影响,主要是根据题目描述确认哪些实体之间有联系,联系类型是哪一种,而后进行连线即可,并不难。
2、补充关系模式:实际考察的是将E-R图转换为关系模式,补充缺失的属性,分成两步:首先需要审题,题目会给出每个关系模式的属性信息,先将题目中的属性信息和问题对应,将缺少的属性全部补充,而后再按照规则转换,即前面所说的规则,按联系的三种对应方式决定要添加哪些字段。
3、情景问答:一般都是给出一段新的描述,要求新增一种实体-联系类型和关系模式,本质也是考察联系类型和E-R图转换为关系模式
- 注意审题,常识以及E-R图转换为关系模式的原则 (主要是联系的归属)
1.4 关系模式设计
- 给定一个X,能唯一确定一个Y,就称X确定Y,或者说Y依赖于x,例如Y=X*X函数。
- 函数依赖又可扩展以下两种规则:
(1)部分函数依赖:A可确定C,(A,B)也可确定C,(A,B)中的一部分 (即A) 可以确定C,称为部分函数依赖。
(2)传递函数依赖:当A和B不等价时,A可确定B,B可确定C,则A可确定C,是传递函数依赖;若A和B等价,则不存在传递,直接就可确定C。
- 函数依赖的公理系统(Armstrong)设关系模式R<U,F>U是关系模式R的属性全集,F是关系模式R的一个函数依赖集。对于R<U,F>来说有以下的:
【几个比较重要的概念】
- 超键:能唯一标识此表的属性的组合;
- 侯选键:超键中去掉冗余的属性,剩余的属性就是候选键;
- 主键:任选一个候选键,即可作为主键;
- 外键:其他表中的主键;
- 主属性:候选键内的属性为主属性,其他属性为非主属性;
- 实体完整性约束:即主键约束,主键值不能为空,也不能重复;
- 参照完整性约束:即外键约束,外键必须是其他表中已经存在的主键的值或者为空;
- 用户自定义完整性约束:自定义表达式约束,如设定年龄属性的值必须在0到150之间。
【第一范式1NF】
● 关系中的每一个分量必须是一个不可分的数据项。通俗地说,第一范式就是表中不允许有小表的存在。比如,对于如下的员工表,就不属于第一范式:
实例:用一个单一的关系模式学生来描述学校的教务系统学生(学号,学生姓名,系号,系主任姓名课程号,成绩)依赖关系(学号->学生姓名,学号->系号,系号->系主任姓名,学号->课程号,(学号,课程号) ->成绩)
【第二范式】
● 如果关系R属于1NF,且每一个非主属性完全函数依赖于任何一个候选码,则R属于2NF。通俗地说,2NF就是在1NF的基础上,表中的每一个非主属性不会依赖复合主键中的某一个列。按照定义,上面的学生表就不满足2NF,因为学号不能完全确定课程号和成绩(每个学生可以选多门课)。
将学生表分解为:
● 学生(学号,学生姓名,系编号,系名,系主任)
● 选课(学号,课程号,成绩)
● 每张表均属于2NF。
第二范式消除了非主属性对主属性的部分函数依赖
【第三范式】
● 在满足1NF的基础上,表中不存在非主属性对码的传递依赖;
继续上面的实例,学生关系模式就不属于3NF,因为学生无法直接决定系主任和系名,是由学号->系编号,再由系编号->系主任,系编号->系名,因此存在非主属性对主属性的传递依赖
将学生表进一步分解为:
学生(学号,学生姓名,系编号)
系(系编号,系名,系主任)
选课(学号,课程号,成绩)
每张表都属于3NF。
【BC范式BCNF】
是指在第三范式的基础上进一步消除主属性对于码的部分函数依赖和传递依赖。通俗的来说,就是在每一种情况下,每一个依赖的左边决定因素都必然包含候选律,如下:
- 上图中,候选键有两种情况:组合键(S,T)或者(S,J),依赖集为(SJ-T,T一可知,STJ三个属性都是主属性,因此其达到了3NF(无非主属性),然而,第二种情况,即(SJ)为候选键的时候,对于依赖T->J,T在这种情况不是候选键,即T-J的决定因素不包含任意候选码,因此上图不是BCNF。
- 要使上图关系模式转换为BCNF也很简单,只需要将依赖T->J变为TS->J即可这样其左边决定因素就包含了候选键之一S
1.5 SQL语言设计
1.5.1 创建表(create table)
CREATE TABLE<表名>(<列名><数据类型>[列级完整性约束条件]
[,<列名><数据类型>[列级完整性约束条件]]...
[,<表级完整性约束条件>]) ;
● 列级完整性约束条件有 NULL (空)和UNTQUE(取值唯一)。
● 表级完整性约束条件有 primary key 和 foreign key 等。
create table stu(sno int not null unique,
sex char(6),
departnum int,
sname char(10),
primary key(sno),
foreign key(departnum) references depart (departnum));
1.5.2 修改表 (alter table)
ALTER TABLE<表名>[ADD<新列名<数据类型>[完整性约束条件]]
[DROP<完整性约束名>]
[MODIFY<列名><数据类型>];
alter table stu add telephone char(11);
alter table stu modify sno char(6);
1.5.3 删除表 (drop table)
DROP TABLE <表名>
drop table stu;
1.5.4 索引
【索引的作用】
(1)通过创建唯一索引,可以保证数据记录的唯一性。
(2)可以大大加快数据检索速度。
(3)可以加速表与表之间的连接,这一点在实现数据的参照完整性方面有特别的意义。
(4)在使用ORDER BY和GROUP BY子句中进行检索数据时,可以显著减少查中分组和排序的时间。
(5)使用索引可以在检索数据的过程中使用优化隐藏器,提高系统性能。
- 索引分为聚集索引和非聚集索引。聚集索引是指索引表中索引项的顺序与表中记录的物理顺序一致的索引。
创建索引
CREATE [UNIQUE] [CLUSTER] INDEX <索引名>ON<表名>(<列名>[<次序>][,<列名>[次序>]]... ) ;
● 次序:可选ASC (升序) 或DSC (降序) ,默认升序。
● UNIQUE:表明此索引的每一个索引值只对应唯一的数据记录。
● CLUSTER:表明要建立的索引是聚簇索引,索引项的顺序是与表中记录的物理顺序一致的索引组织。
删除索引
DROP INDEX<索引名>
1.5.5 视图
视图不是真实存在的基本表,而是一个虚拟表,视图所对应的数据并不实际地以视图结构存储在数据库中,而是存储在视图所引用的表中。使用视图的优点和作用如下:
(1)可以使视图集中数据、简化和定制不同用户对数据库的不同数据要求。
(2)使用视图可以屏蔽数据的复杂性,用户不必了解数据库的结构,就可以方便地使用和管理数据简化数据权限管理和重新组织数据以便输出到其他应用程序中。
(3)视图可以使用户只关心他感兴趣的某些特定数据和所负责的特定任务,而那些不需要的或者无用的数据则不在视图中显示。
(4)视图大大地简化了用户对数据的操作
(5)视图可以让不同的用户以不同的方式看到不同或者相同的数据集。
(6)在某些情况下,由于表中数据量太大因此在表的设计时常将表进行水平或者垂直分割,但表的结构的变化对应用程序产生不良的影响。
(7)视图提供了一个简单而有效的安全机制。
创建视图
CREATE VIEW 视图名(列表名)
AS SELECT 查询子句[WITH CHECK OPTION];
- 子查询可以是任意复杂的 select 语句,但通常不允许含有 order by 和distinct。with check option 表示执行 update、insert、delete 操作时保证更新、插入、删除的行满足视图定义中的条件。“
- 组成视图的属性列名或者全部省略或者全部指定。如果省略属性列名,则隐含该视图由 select子查询目标列的主属性组成。
create view cs-stu as select * from stu where depart='cs' with check option;
删除视图
drop view 视图名
drop view cs-stu;
1.5.6 查询语句格式
SELECT [ALL | DISTINCT] <目标列表达式> [目标列表达式>]..
FROM <表名或视图名> [,<表名或视图名>]
[WHERE<条件表达式>]
[GROUPBY<列名1>[HAVING<条件表达式>]]
[ORDER BY<列名2>[ASC|DESC]...]
- SOL查询中的子句顺序为SELECT、FROM、WHERE、GROUP BY、HAVING 和ORDER BY其中,SELECT、FROM 是必须的,HAVING条件子只能与GROUP BY搭配起来使用。
(1)SELECT子句对应的是关系代数中的投影运算,用来列出查询结果中的属性。其输出可以是列名表达式、集函数(AVG、COUNT、MAX、MIN、SUM),DISTINCT选项可以保证查询的结果集中不存在重复元组。
(2)FROM子句对应的是关系代数中的笛卡儿积,它列出的是表达式求值过程中需扫描的关系,即在FROM子句中出现多个基本表或视图时,系统首先执行笛卡儿积操作。
(3)WHERE子句对应的是关系代数中的选择谓词。WHERE 子句的条件表达式中可以使用的运算符如表所示。 - 简单查询:只涉及一张表。查询计算机系学生的学号和姓名。
select sno,sname from stu where depart='CS‘;
-
连接查询:查询涉及两个以上的表。查询选修了课程号为C1的学生号和学生姓名。
select sno,sname from SSC where S.sno=SCsno and SCcno='C1';
- 子查询:也称为嵌套查询,是指一个select-from-where查询块可以嵌入另一个查询块之中,SQL中允许多重嵌套。查询选修了课程号为C1的学生号和学生姓名。
select sno,sname from S where sno in (select sno from SC where cno=’ C1');
- 聚集函数:是以一个值的集合为输入,返回单个值的函数,SQL提供的聚集函数如下:
- 使用ANY和ALL谓词必须同时使用比较运算符用聚集函数实现子查询通常比直接用ALL或ANY查询效率更高,二者等价转换如下:
1.6.7 分组查询
● group by<列名1>[having <条件表达式>];
● group by 按某一列分组,一般只能select分组的列以及使用聚集函数
● 在group by子句后面加一个having子句,对分组设置过滤条件,可以使用聚集函数,注意:
● 空值在任何聚集操作中都会被忽视,如求和、求平均值和计数都没有影响,如count(*)是某个关系中所有元组数组之和,但count(A)却是A属性非空的元组个数之和。
● NULL值可以看做分组属性中的一个一般的值,例如,在select A,avg(B) from R中,当A的属性值为空时,就会统计A=NULL的所有元组中B的均值。
● 查找订单总金额小于2000的客户:
select customer, sum(orderPrice) from orders group by customer having sum(orderPrice) <2000;
1.5.8 其他操作
- 更名操作(as子句: ld name as new-name既可以出现在select子句中,也可以出现在from子句中select sname as 姓名, sage as 年 from S where SD=' CS';
- 字符串操作作对于字符串进行的最通用的操作时使用操作符like的模式匹配,使用两个特殊的字符描述:
%:匹配任意字符串
_:匹配任意一个字符模式是大小写敏感的,例如zhang%,mary_ 等。
select sname from S where saddress like '%张江%'; - 集合操作:在关系代数中用集合的并、交、差来组合关系,SQL提供了对应的操作,但是查询的结果必须具有相同的属性和类型列表。保留字union、intersect、 except分别对应并、交、差;
- 查询选修了180101号或180102号课程或二者都选修了的学生学号、课程号和成绩。
(SELECT学号课程号,成绩 FROM学习WHERE 课程号=180101)UNION
(SELECT学号课程号成绩 FROM学习WHERE 课程号=180102)
● UNION运算自动去除重复。如果想保留所有的重复,则必须用UNION ALL代替UNION,目查询结果中出现的重复元组数等于两个集合中出现的重复元组数的和。 - 查询同时选修了180101和180102号课程的学生学号、课程号和成绩。
(SELECT学号,课程号,成绩 FROM学习 WHERE 课程号=180101) INTERSECT
(SELECT学号课程号,成绩 FROM学习 WHERE 课程号=180102)
● INTERSECT运算自动去除重复,如果想保留所有的重复,必须用INTERSECT ALL代替● INTERSECT结果中出现的重复元组数等于两集合出现的重复元组数里较少的那个。 - 查询选修了180101号课程的学生中没有选修180102号课程的学生学号、课程号和成绩(SELECT学号课程号,成绩FROM学习WHERE课程号=180101)EXCEPT
(SELECT学号课程号,成绩 FROM学习WHERE 课程号=180102)
● EXCEPT运算自动去除重复,如果想保留所有的重复,必须用EXCEPT ALL代替EXCEPT,结果中出现的重复元组数等于两集合出现的重复元组数之差(前提是差是正值)
SQL对视图更新必须遵循以下规则:
(1)从多个基本表通过连结操作导出的视图不允许更新。
(2)对使用了分组、集函数操作的视图则不允许进行更新操作。
(3)如果视图是从单个基本表通过投影、选取操作导出的则允许进行更新操作,且语法同基本表 。
- 和过程定义不同的是Create view子句会在数据库中建立视图定义,该视图定义会一直保存,直到执行drop view 命令。但是,with子句提供了定义一个临时视图的方法,该定义只对with子句出现的那条查询有效。
- 插入insert
INSERTINTO 表名称 VALUES(值1值2,....)INSERTINTO table name(列1,列2...) VALUES (值1, 值2....)INSERT INTO Persons VALUES (GatesBill,Xuanwumen 10Beijing)INSERT INTO Persons (LastName, Address) VALUES (WilsonChamps-Elysees’) - 删除delete
DELETE FROM 表名称WHERE 列名称=值DELETE FROM Person WHERE LastName=Wilson' - 更新update
UPDATE 表名称SET 列名称=新值WHERE列名称=某值UPDATE Person SET FirstName =Fred' WHERE LastName = Wilson'
1.5.9 约束
- 主键约束primary key
- 完整性约束条件作用的对象有关系、元组和列
- 完整性控制具有的功能:定义功能、检测功能和处理功能。
- 检查是否违背完整性约束的时机有两种: 在一条语句执行完后立即检查称为立即执行约束;需要延到整个事务执行完后再检查称为延迟执行约束。
- 实体完整性:关系中只能由一个主键,声明主键有两种方法;
- 属性类型后加primary key 保留字;
- 在属性列表的最后增加一行primary key(属性或属性组)
外键约束foreign key
参照完整性定义格式:
foreign key(属性名)references 表名(属性)[on delete cascade set nullj;
references指明外键对应于哪个表的主键;
on delete cascade指明删除被参照关系的元组时,同时删除参照关系中的元组:
set null表示空值。
属性值上的约束,属性值上的约束通过下面关键字进行
not null:不允许空值
unique:唯一值
check:属性值要满足指定条件
create table students (sno char(8)not null unique,
sname char(10),
sage int,
sdept char(20),
primary key(sno),
foreign key(sdept) references D(dept),
check(sage >=15 and sage <= 22))
1.5.10 授权grant
GRANT<权限>[<权限>]... [ON<对象类型><对象名>)TO<用户>[,<用户]>]...[WITH GRANT OPTION]
- 若指定了WITH GRANT OPTION子句,那么获得了权限的用户还可以将权限赋给其他用户: 接受权限的用户可以是单个或多个具体的用户,PUBLIC参数可将权限赋给全体用户。不同类型的操作对象有不同的操作权限,常见的操作权限如表所示。
grant all privileges on table S,PJ to user1, user2;
grant insert on table S to user1 with grant option;
1.5.11 收回权限revoke
REVOKE<权限>[,<权限>]... [ON<对象类型><对象名>]FROM<用户>[,<用户]>]... ;
revoke all privileges on table S,PJ from user1,user2;revoke select on table S from user1;
1.5.12 触发器
- 触发器和存储过程
● 触发器trigger是与表事件相关的特殊的存储过程,它的执行不是由程序调用,也不是手工启动,而是由事件来触发。
● 触发器经常用于加强数据的完整性约束和业务规则等;
● 触发器与存储过程的唯一区别是触发器不能执行execute语句调用,而是在用户执行transact-SQl语句时自动触发执行。
● 存储过程:是在大型数据库系统中,一组为了完成特定功能的SQL 语句集,存储在数据库中,经过第一次编译后再次调用不需要再次编译,用户通过指定存储过程的名字并给出参数(如果该存储过程带有参数)来执行它。 - 触发器为数据库对象,当创建一个触发器时必须指定:
(1)名称;
(2)在其上定义触发器的表;
(3)触发器将何时激发;
(4)指明触发器执行时应做的动作。 - 触发动作实际上是一系列SQL语句,可以有两种方式:
(1)对被事件影响的每一行(FOR EACH ROW)-每一元组执行触发过程,称为行级触发器。(2)对整个事件只执行一次触发过程(FOREACHSTATEMENT),称为语级触发器。该方式是触发器的默认方式。 - 触发器的定义包括两个方面:指明触发器的触发事件,指明触发器的执行动作。
创建触发器:
(1)BEFORE:指示DBMS在执行触发语之前激发触发器
(2)AFTER:指示DBMS在执行触发语之后激发触发器。
(3)DELETE:每当一个DELETE语从表中删除一行时激发触发器。
(4)INSERT:每当一个时SERT 语句向表中插入一行时激发触发器
(5)UPDATE:每当UPDATE 语修改由OF子指定的列值时,激发触发器。如果忽略OF子,每当UDPATE 语修改表的任何列值时DBMS都将激发触发器
(6)REFERENCING<临时视图名>:指定临时视图的别名。在触发器运行过程中,系统会生成两个临时视图,分别存放被更新值 (旧值)和更新后的值(新值》。对于行级触发器,默认临时视图名分别是OLD 和NEW (oracle,在MS中,为Deleted,Inserted) ;对于语句级触发器,默认临时视图名分别是OLD-TABLE和NEW-TABLE。一旦触发器运行结束,临时视图就不在。
(7)WHEN<触发条件>:指定触发器的触发条件。当满足触发条件时,DBMS才激发触发器。触发条件中必须包含临时视图名,不包含查询。
CREATE TRIGGER<触发器名>[BEFORE | AFTER)([DELETE | INSERT | UPDATEOF [列名清单]])ON表名
[REFERENCING<临时视图名>][WHEN<触发条件>]
BEGIN
<触发动作>
END[触发器名]
【修改触发器】
ALTER TRIGGER<触发器名> [(BEFORE | AFTER]([DELETE | INSERTIUPDATEOF[列名清单]])
ON表名 | 视图名
AS
BEGIN
要执行的SQL语句
END
【删除触发器】
drop trigger trigger name
1.6 事务并发设计
- 事务:由一系列操作组成,这些操作,要么全做,要么全不做,拥有四种特性,详解如下:(操作)原子性:要么全做,要么全不做。(数据)一致性:事务发生后数据是一致的,例如银行转账,不会存在A账户转出,但是B账户没收到的情况。(执行)隔离性:任一事务的更新操作直到其成功提交的整个过程对其他事务都是不可见的,不同事务之间是隔离的,互不干涉。(改变)持续性:事务操作的结果是持续性的。
- 事务是并发控制的前提条件,并发控制就是控制不同的事务并发执行,提高系统效率,但是并发控制中存在下面三个问题:
丢失更新:事务1对数据A进行了修改并写回事务2也对A进行了修改并写回此时事务2写回的数据会覆盖事务1写回的数据,就丢失了事务1对A的更新。即对数据A的更新会被覆盖
不可重复读:事务2读A,而后事务1对数据A进行了修改并写回,此时若事务2再读A,发现数据不对。即一个事务重复读A两次,会发现数据A有误。
读脏数据:事务1对数据A进行了修改后,事务2读数据A,而后事务1回滚,数据A恢复了原来的值,那么事务2对数据A做的事是无效的,读到了脏数据。
- X锁是排它锁(写锁)。若事务T对数据对象A加上X锁,则只允许T读取和修改其他事务都不能再对A加任何类型的锁,直到T释放A上的锁。
- S锁是共享锁(读锁)。若事务T对数据对象A加上S锁,则只允许T读取A,但不能修改A,其他事务只能再对A加S锁 (也即能读不能修改),直到T释放A上的S锁。
共分为三级封锁协议,如下:
一级封锁协议:事务在修改数据R之前必须先对其加X锁,直到事务结束才释放。可解决丢失更新问题:
二级封锁协议:
一级封锁协议的基础上加上事务T在读数据R之前必须先对其加S锁,读完后即可释放S锁。
可解决丢失更新、读脏数据问题:
三级封锁协议:
级封锁协议加上事务T在读取数据R之前先对其加S锁,直到事务结束才释放可解决丢失更新读脏数据、数据重复读问题
- 串行调度(serial schedule) 是指多个事务依次串行执行,且只有当一个事务的所有操作都执行完后才执行另一个事务的所有操作。
- 并发调度 (concurrent schedule): 利用分时的方法同时处理多事务”其执行的结果与串行调度执行的结果相同,则称这个并发调度是正确的。可恢复调度:若事务Ti提交失败,则应当撤销Ti的影响以保证其原子性。在允许并发执行的系统中,还必须确保依赖于Ti的任何事务也中止。例如,Ti要读Ti写的数据,则称T 依赖于Ti。
- 可恢复调度(recoverable schedule) 应满足: 当事务 要读事务Ti 写的数据时,事务Ti必须要先于事务Ti 提交
- 可串行化的调度:多个事务的并发执行是正确的当且仅当其结果与某一次序串行地执行它们时的结果相同,称这种调度策略是可串行化的调度(serializability schedule)。
- 冲突可串行化
冲突 (conflict):当li和li是不同事务在相同的数据项上操作的命令,月至少有一个是write 命令时,则称i与ii是冲突的。 - 等价调度:设l与i是调度S 的两条连续的命令,若与是不同事务的命令且不冲突,则可以交换li与ij的顺序得到一个新的调度S*。我们称S 与S*是等价的。
【两段锁协议】
- 两段锁协议:是指对任何数据进行读写之前必须对该数据加锁在释放一个封锁之后,事务不生长阶段(加锁、扩展阶段)再申请和获得任何其他封锁。每个事务的执行可以分为两个阶段和衰退阶段 (解锁、收缩阶段)。
- 加锁阶段:在该阶段可以进行加锁操作。在对任何数据进行读操作之前要申请并获得S锁,在进行写操作之前要申请并获得X锁。加锁不成功,则事务进入等待状态,直到加锁成功才继续执行。
- 解锁阶段:当事务释放了一个封锁以后,事务进入解锁阶段,在该阶段只能进行解锁操作不能再进行加锁操作
- 如果事务部遵循两段锁协议,那么它们的并发调度是可串行化的。两段锁是可串行化的充分条件,但不是必要条件。需要注意的是采用两段锁协议也有可能产生死锁,这是因为每个事务都不能及时解除被它封锁的数据,可能会导致多个事务互相都要求对方己封锁的数据不能继续运行。
- 封锁的粒度封锁的粒度是被封锁数据目标的大小,在关系数据库中封锁粒度有属性值、属性值集、元组关系、索引项、整个关系数据库等几种。
- 封锁粒度小则并发性高,但开销大,封锁粒度大则并发性低,但开销小。
【数据库事务的四种隔离级别】
数据库事务的四种隔离级别数据库事务的隔离级别有4个,由低到高依次为Readuncommitted、Read committed.Repeatable read、Serializable.
- READ UNCOMMITTED:读未提交,这是事务最低的隔离级别,它允许另外一个事务可以看到这个事务未提交的数据
- READ COMMITTED: 读提交,保证一个事务修改的数据提交后才能被另外一个事务读取另外一个事务不能读取该事务未提交的数据。解决丢失更新、读脏数据问题。
- REPEATABLE READ:重复读,在开始读事务时,不允许修改操作。进一步解决了不可重复读问题。
- SERIALIZABLE:这是花费最高代价但是最可靠的事务隔离级别。事务被处理为串行化执行。
【游标】
一条SQL 语句可产生或处理多条记录。而主语言是面向记录的,一组主变SQL 语言是面向集合的量一次只能放一条记录,所以,引入游标,i通过移动游标指针来决定获取哪一条记录。与游标相关的SQL语句有四条:
(1)定义游标,格式如下
EXEC SOL DECLARE <游标名> CURSOR FOR
<SELECT语句>
END EXEC
这是一条说明性语句,定义中的 SELECT 语句并不立即执行。
(2) 打开游标,格式如下:
EXEC SQL OPEN <游标名> END EXEC
该语句执行游标定义中的 SELECT 语句,同时游标处于活动状况。游标是一个指针,此时指向查询结里的第一行之前。
(3)推进游标,格式如下
EXEC SQLFETCH FROM<游标名>INTO<变量表>ENDEXEC该语句使用时,游标推进一行,并把游标指向的行(称为当前行)中的值取出,送到共享变量中。变量表由用逗号分开的共享变量组成。该语句常置于宿主语言程序的循环结构中。
(4)关闭游标,格式如下:EXEC SQLCLOSE<游标名>END EXEC该语句关闭游标,使它不再和查询结果相联系。关闭了的游标,可以再次打开,与新的查询结果相联系。
1.7 数据库恢复设计
1.7.1 事务故障
- 数据库故障主要分:事务故障、系统故障和介质故障。
- 事务故障:是由于程序执行错误而引起事务非预期的、异常终止的故障。通常有如下两类错误引起事务执行失败。
(1)逻辑错误。如非法输入、找不到数据、溢出、超出资源限制等原因引起的事务执行失败(2)系统错误。系统进入一种不良状态(如死锁),导致事务无法继续执行 - 对于不可以预期的错误应用程序无法处理,是由DBMS 系统实现故障恢复的。如非法输入、运算溢出等。非预期的故障如非法输入是由约束机制检查并恢复的。事务故障通常指非预期的故障事务故障意味着事务没有达到预期的终点,因此数据库可能处于不正确状态。恢复程序要在不影响其他事务运行的情况下,强行回滚该事务,即撤销该事务己经做出的任何对数据库的修改,这类恢复操作称为事务撤销 (UNDO)。
恢复过程:
(1)反向 (从后向前)扫描日志文件查找该事务的更新操作;
(2)对该事务的更新操作执行逆操作,也就是将日志记录更新前的值写入数据库;
(3)继续反向扫描日志文件,查找该事务的其他更新操作,并作同样处理;
(4)如此处理下去,直到读到了此事务的开始标记,事务故障恢复就完成了。 - 事务故障的恢复由系统自动完成,对用户是透明的。
1.7.2 系统故障
系统故障(通常称为软故障):是指硬件故障、软件(如DBMS、OS 或应用程》漏的影响,导致丢失了内存中的信息,影响正在执行的事务,但未破坏存储在外存上的信息。这种情况称为故障 - 停止假设。
- 系统故障会使数据库的数据不一致,原因有两个:
(1)是未完成的事务对数据库的更新可能己写入数据库;
(2)是己提交的事务对数据库的更新可能还在缓冲区中没来得及写入数据库。因此恢复操作就是要撤销故障发生时未完成的事务,重做 (REDO) 已提交的事务。 - 恢复过程:
(1)正向 (从头到尾)扫描日志文件,找出故障发生前已经提交的事务 (这些事务既有BEGINTRANSACTION 记录,也有COMMIT记录),将其事务标识记入重做 (REDO) 队列。同时找出故障发生时尚未完成的事务 (这些事务只有BEGIN TRANSACTION 记录,无相应的COMMIT记录),将其事务标识记入撤销 (UNDO) 队列;
(2)反向扫描日志文件,对每个UNDO事务的更新操作执行逆操作,也就是将日志记录中更新前的值写入数据库。对每个REDO事务重新执行日志文件登记的操作,也就是将日志记录中更;
(3)正向扫描日志文件,新后的值写入数据库。 - 系统故障是在系统重启之后自动执行的,对用户是透明的
1.7.3 介质故障
介质故障(称为硬件故障):是指外存故障,例如磁盘损坏、磁头碰撞,瞬时强磁场干扰等。这类故障将破坏数据库或部分数据库,并影响正在存取这部分数据的所有事务,日志文件也被破坏。
- 恢复过程:
(1)装入最新的数据库后备副本,使数据库恢复到最近一次转储时的一致性状态;
(2)转入相应的日志文件副本,重做已完成的事务。 - 介质故障的恢复需要DBA的介入,具体的恢复操作仍由DBMS完成。