数据库

01 数据管理基本概念

数据&信息

  • 数据:无意义。数据+解释=信息
  • 信息:影响动态系统的状态的事件。

数据管理

  • 数据定义
  • 数据组织、存储、管理
  • 数据操纵
  • 数据库事务管理和运行管理
  • 数据库的建立与维护

数据库系统

由应用程序、数据库、数据库管理系统和用户组成。

  • 数据共享:不同用户使用数据重叠。
  • 数据独立性:数据库中的数据与应用程序之间不存在依赖关系。
    • 物理独立性:数据库(从光盘挪到磁盘:物理层修改),程序不影响。
    • 逻辑数据独立性:修改数据库的逻辑模式而不必重写应用程序的能力。
  • 方便的用户接口(SQL)
  • 统一的数据管理与控制功能
    • 数据完整性:正确性,有效性和相容性。
    • 数据安全性:主动安全(有效防止数据被非法使用&修改),被动安全(遭到破坏可以完全恢复)
    • 并发控制

02 数据模型

数据模型:是模型的一种,是现实世界数据特征的抽象,是用来描述数据的一组概念和定义。

概念模型

对现实世界的第一层抽象。

概念数据模型

  • 是独立于计算机系统的数据模型,不涉及信息在计算机中的表示,只用来描述某个特定组织所关心的信息结构,是对现实世界的第一层抽象。
  • 按用户的观点对数据建模,强调其语义表达能力,是用户和数据库设计人员之间进行交流的语言和工具。

要求:强语义表达能力,方便直接的表达应用中的各种语义知识

ER数据模型

最常用的一种概念数据模型

抽象手段

分类
  • 定义某一类感念作为现实世界中一组对象的类型。
  • 在特定的上下文里,这些对象具有某些共同特性和行为。
  • 大学里的学生,奥运会的赛事,公交公司的司机…
聚集
  • 定义某一类型的组成成分
  • 根据上下文管理需求,给出指定类型的特征集合
  • 学生:学号、姓名、年龄等特征组成

基本元素

  • 实体:客观存在并可以相互区分的客观事物或抽象事件。分类
    • 实体集:同型实体的集合。
  • 属性:实体所具有的某一特性。聚集
    • 域:是一组具有相同数据类型的值的集合
    • 类型:
      • 简单属性:不可再分。eg:学号。
      • 复合属性:可以划分更小的属性。eg:街道=家庭住址+门牌号码。
      • 单值属性:每一个特定的实体在该属性上的取值唯一。
      • 多值属性:特定实体在该属性上有多于一个的取值(eg:电话)
    • 键(key):
      • 实体集中能唯一标识实体的属性或属性组称为实体集的键.
      • >2>2是复合键。
  • 联系:笛卡尔积。

ER图

🍰 实体:矩形框

🍰 属性:椭圆框并用连线连到相应实体。

🍰 联系:菱形框并用连线与有关的实体相连。

联系的元:参与联系的实体的个数。

联系的基数比约束:1:1,1:n,m:n(谁是1那边谁标1:领导1工人n)

多元联系中使用箭头——知道了其他几种就可以确定箭头指向的信息:

约束

约束:数据库的断言(对插入数据库中的数据进行限定)

非空约束,唯一值约束,主键约束,外键约束,Check约束

键约束

超键:是实体集中的一个或一组属性,可以唯一的确定每一个实体。

候选键:某个超键的最小集。

存在多个候选键,可以任选一个作为主键。

建模准则

能抽象为属性的,就不要抽象为实体。符合以下之一才被抽象为实体:

  • 至少一个非键属性。
  • 处于“一对多”或“多对多”联系中“多”那一端。

逻辑模型

对现实世界的第二层抽象,与DBMS有关。

  • 直接面向数据库的逻辑结构,是对现实世界的第二层抽象。它直接与DBMS有关,有严格的形式化定义,以便在计算机系统中实现。
  • 有一组严格定义的无二义性语法和语义的DB语言
  • 层次模型、网状模型、关系模型等
  • 是区分不同类型数据库的依据,很大程度上决定了数据库的性能和应用范围

通常所说的数据模型就是逻辑数据模型

三要素:数据结构,数据操作和数据约束。

物理模型

  • 反映了数据在存储介质上的组成结构,并描述了访问机制
  • 如何表达记录结构、记录顺序和访问路径等信息

03 关系模型

逻辑数据结构三要素:数据结构、数据操作和数据约束

关系模型:二维表格结构表示实体及实体之间的联系的模型。对关系的数学理论描述

关系模式:对关系的结构描述

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETkDliqrlipvlpYvmlpfnmoTlvKDlkIzlraY,size_20,color_FFFFFF,t_70,g_se,x_16

关系数据结构

关系与关系间有公共属性,说明两个关系有联系。

只要把的所有的实体及其属性用关系框架来表示,同时把实体之间的关系也用关系框架来表示,就可以得到一个关系模型。

性质

  • 不能出现相同元组(笛卡尔积每一个元素叫做一个n元组,即关系表的一行)

  • 关系中元组的顺序(即行序)无关紧要。

  • 属性的顺序也无关紧要,应连同属性名一起交换。

  • 统一属性名下的个属性必须来自同一个域,是同一类型的数据。

  • 关系中各个属性必须有不同的名字,不同的属性可来自同一个域,即它们的分量可以取自同一个域。(eg:职业&兼职)

  • 每一分量必须是不可分的数据项。所有属性值都是原子的,是一个确定的值,而不是值的集合。不可“表中有表”。满足此条件的关系称为规范化关系,否则称为非规范化关系

ER模型向关系模型转化

实体类型转换

每个实体类型转换成一个关系模式,实体的属性即为关系模式的属性,实体标识符即为关系模式的键。

二元联系类型的转换

  • m:n

  • 1:n:直接合并。将1合并到n端。

关系的完整性

  • 域完整性
    • 属性值应符合域的取值范围,增强数据类型
    • 对是否为NULL也是域完整性约束的一部分
  • 实体完整性
    • 主键(非空,取值唯一)
  • 参照完整性
    • 外键:关系与关系之间的引用(空值|等于被参照关系中某个元组的主键值)
  • 用户定义的完整性:对某一具体关系数据库的约束条件。

关系代数

查询的条件要使用关系运算表达式来表示

  • 运算对象:关系。
  • 运算结果:关系。
  • 运算符:四类。

基本运算:集合并、集合差、广义笛卡儿积、选择、投影

集合运算符

行的角度

并交差运算:必须是相容的:

  • 关系R和S同元,属性数目必须相同。
  • 对于所有i,R的第i格属性的域必须和S的第i个属性的域相同。

广义笛卡尔积:

交运算:

RS=R(RS)R\cap S=R-(R-S)

专门的关系运算符

行和列的方向同时选择

选择:选择某些元组形成一个新的关系。(选择符合条件的行/元组)

\sigma_{F}(R)=\{t|t\in R \and F(t)=true \}。R是关系名,σ\sigma是选择运算符,F是逻辑表达式。

投影:选择指定的属性,形成一个可能含有重复行的表格,删除重复行形成新关系。(投影可改变关系的属性次序,新关系与原关系不相容)

πA(R)={r.ArR}\pi_A(R)=\{r.A|r\in R\},R是关系名,π\pi是投影运算符,A是被投影的属性或属性集

连接:两个表之间的运算,一对多联系的父子关系。一般是由参照关系的外键和被参照关系的主键控制。

R \underset{A\theta B}\bowtie S=\{t|t=\and r\in R\and s\in S\and r[A]\ \theta\ s[B]\}

  • 自然连接:从两个关系的广义笛卡儿积中选取在相同属性列上取值相等的元组,并去掉重复的属性列。特殊的等值连接。

  • 外连接:自然连接 + 失配的元组。

  • 自连接:两张一模一样的表连接。

:至少。R÷S=πx(R)πx((πx(R)×S)R)R \div S=\pi_{x}(R)-\pi_{x}((\pi_{x}(R)\times S)-R).

即所有满足被除项的判断,排除不在被除项的属性

04 SQL语言

查询语言

单表查询

选择列

1
SELECT Sno,Sname FROM Student;

查询经计算的值

  • LOWER(Sdept):将所有字母小写。

    1
    SELECT Sname,2022-Sage,LOWER(Sdept) FROM Student;
  • 使用列别名改变查询结果的列标题:

    1
    2
    SELECT Sname AS NAME,'Year of Birth: ' AS BIRTH,
    2022-Sage AS BIRTHDAY,LOWER(Sdept) AS DEPARTMENT FROM Student;

选择元组

  • 保留重复行(ALL,可省略)。消除取值重复的行(DISTINCT)DISTINCT短语的作用范围是所有目标列,放在属性的最前面!!!

  • 查询满足条件的元组:where。

    1
    WHERE Sdept IN('IS','MA','CS');

    • between ... and ...包括边界):

      1
      select sanme from student where sage between 20 and 23;
    • 字符串匹配:

      %任意长度(可以为0)的字符串,_单个字符。

      1
      WHERE <Attribute> LIKE <pattern>;

      查询中本身含有%or_,使用ESCAPE。

      1
      WHERE Cname LIKE 'DB\_Design' ESCAPE ‘\';
  • 涉及空值的查询(任意与NULL比较结果都为Unknown)

    三值逻辑计算:TRUE = 1, FALSE = 0, and UNKNOWN = ½。AND = MIN; OR = MAX, NOT(x) = 1-x

    IS NULL:是空值。

排序

ASC:升序。空值最后显示。

DESC:降序。空值最先显示。

聚集和分组

聚集

空值不加入计算。

  • 计数 COUNT([DISTINCT|ALL] <列名> | *)

  • 计算总和 SUM ([DISTINCT|ALL] <列名>)

  • 计算平均值 AVG([DISTINCT|ALL] <列名>)

  • 求最大值 MAX([DISTINCT|ALL] <列名>)

  • 求最小值 MIN([DISTINCT|ALL] <列名>)

GROUP BY

对每一个组进行集操作。

Having

只有满足HAVING短语指定条件的组才输出

HAVING短语与WHERE子句的区别:作用对象不同。

  • WHERE子句作用于基表或视图,从中选择满足条件的元组。不能使用集函数
  • HAVING短语作用于组,从中选择满足条件的组。可以使用集函数

HAVING子句中出现的列只能是在group by子句或集函数中出现的列。

多表查询

连接查询

笛卡尔积

也可以不带连接谓词。

1
SELECT Student.*,SC.* FROM Student CROSS JOIN SC;
等值连接
1
SELECT Student.sno,sname,cno FROM Student ,SC WHERE Student.Sno=SC.Sno;

自然连接:等值连接特殊情况。把目标列中重复的属性列去掉。

自连接:一个表与自己连接。

1
SELECT FIRST.Cno,SECOND.Cpno FROM Course AS FIRST,Course AS SECOND WHERE FIRST.Cpno = SECOND.Cno;

子查询

在FROM中嵌套查询语句,但不能order!

子查询中不能使用order by

1
SELECT Sname FROM Student WHERE Sno IN(SELECTSno FROM SC WHERE Cno='2');

带IN谓词的子查询

查询与刘晨在同一个系学习的学生:

1
select sno,sname,sdept from student where sdept in (select sdept from student where sname='刘晨')

如果能确切知道内层查询返回单值时,可使用比较运算符,比如上面句子可把IN改为=。

子查询一定跟在比较符后面

带有ANY或ALL谓词的子查询

  • ANY:任意一个值
  • ALL:所有值

查询其他系中比信息系任意一个(其中某一个)学生年龄小的学生姓名和年龄:

1
select sname,sage from student where sage<any(select sage from student where sdept='IS') and sdept!='IS';

用集函数实现子查询通常比直接用ANY或ALL查询效率要高

1
select sname,sage from student where sage<(select max(sage) from student where sdept='IS')and sdept!='IS';

带有EXISTS谓词的子查询

查询所有选修了1号课程的学生姓名

1
select sname from student where exists(select * from sc where sno=student.sno and cno='1');

集合查询

并:UNION。交:INTERSECT。差:EXCEPT。

DDL语言

基本表

定义表

1
2
3
4
create table <table_name>(
<列名> <数据类型>[<列级完整性约束条件>],
....
);

列级完整性约束条件:

  • not null:非空。
  • unique:取值唯一。
  • primary key:主键约束。
  • references:参照完整性约束。

数据类型:

  • char(4):定长字符串。
  • varchar(n):变长字符串,n为字符串最大长度。

删除表

1
drop table student;

修改表

1
2
3
4
alter table <table_name>
[add <新列名> <数据类型> [完整性约束]]
[drop <完整性约束名>]
[modify <列名> <数据类型>]

add:增加心列和新的完整性约束条件。

drop:删除指定的列或完整性约束条件。

modify:修改列名和数据类型。

DML语言

插入

1
insert into <table_name> [(key1,key2...)] values (value1,value2...);

没提到的属性取空值。

插入子查询的结果:

1
2
3
4
insert into deptage(sdept,avgage) values
select sdept,avg(sage)
from student
group by sdept;

更新

1
update <table_name> set key1=value1,key2=value2...where <conditions>;

计算机系全体学生成绩清零(子查询):

1
2
3
update sc set grade=0
where 'cs'=
(select sdept from student where student.sno=sc.sno);

删除

1
delete from <table_name> where <conditions>;

DCL语言

视图

一种虚表,从一个或几个基本表/视图中导出的表,在数据字典中存储的是一条select语句。

带表达式的视图必须明确定义组成视图的各个属性列名

1
2
3
4
5
create view is_student[列名1,列名2..]
as
select sno,sname,sage
from student
where sdept='is';

DBMS在执行create view语句时只是把视图的定义存入数据字典,并没有执行select

对于可更新视图,可以对视图执行数据更新操作,数据库会根据视图定义去更新对应的基本表数据

不建议以select *方式创建视图,可延展性差(基表被破坏后,视图不能正常工作)

05 数据库编程

  • 数据库内部应用:效率高,适用于例行的数据分析维护功能
  • 数据库外部应用:开发灵活,功能与可移植性更强

数据库内部编程

存储过程

多次重复使用的代码编写成过程。

1
2
3
4
5
6
create procedure <procedure_name>(
[in/out/inout]param_name type[,...]
)
[begin]
sql_statement
[end]

in输入参数,out输出参数,inout输入输出参数,既表示调用者向过程传入值,又表示过程向调用者传出值。

eg:

1
2
3
4
create procedure mypro(in a int,in b int,out sum int) 
begin
set sum = a+b;
end;

删除:

1
drop procedure procedure_name

激活存储过程的执行:

1
call procedure_name(param_name type[,...])

变量

1
DECLARE variable_name [,variable_name...] datatype [DEFAULT value];

datatypeMYSQL的数据类型,default声明默认值。

eg:declare name varchar(20) default ‘jack’

变量赋值:

1
SET 变量名 = 表达式值 [,variable_name = expression ...]

流程控制

if
1
2
3
4
5
6
7
if num<0 then -- 条件开始
select '负数';
elseif num=0 then
select '不是正数也不是负数';
else
select '正数';
end if;-- 条件结束
case
1
2
3
4
5
case -- 条件开始
when num<0 then select '负数';
when num=0 then select '不是正数也不是负数';
else select '正数';
end case; -- 条件结束
while
1
2
3
4
while num<10 do -- 循环开始
set num = num+1;
set sum = sum+num;
end while; -- 循环结束
repeat

类似do...while

1
2
3
4
5
repeat-- 循环开始
set num = num+1;
set sum = sum+num;
until num>=10
end repeat;
loop

leave相当于break,iterate相当于continue

1
2
3
4
5
6
7
loop_sum:loop-- 循环开始
set num = num+1;
set sum = sum+num;
if num>=10 then
leave loop_sum;
end if;
end loop loop_sum;

常用数据库函数与命令

显示存储过程:

1
SHOW PROCEDURE STATUS;

显示特定数据库的存储过程

1
SHOW PROCEDURE status where db = 'schooldb';

显示特定模式的存储过程,要求显示名称中包含“my”的存储过程:

1
SHOW PROCEDURE status where name like '%my%';

显示存储过程“mypro1”的源码:

1
SHOW CREATE PROCEDURE mypro1;

嵌入式SQL

赋值:

1
2
declare v_score int;
select score into v_score from sc where cno=55 and stuid=001;

set值:

1
2
set v_score=v_score+1;
update sc set score=v_score where cno=55 and stuid=001;

动态SQL

1
2
3
4
5
6
7
8
9
10
CREATE PROCEDURE count_field(IN FIELDNAME VARCHAR(255), IN 
FIELDVALUE INT)
BEGIN
SET @sql = CONCAT('SELECT COUNT(*) FROM stu WHERE ‘,
FIELDNAME, ' = ?’);
PREPARE stmt FROM @sql;
SET @fieldvalue = FIELDVALUE;
EXECUTE stmt USING @fieldvalue;
DEALLOCATE PREPARE stmt;
END;

游标编程

对查询语句返回的行结果集中的每一行进行单独处理。

主要功能:

  • 定位到结果集中的指定行
  • 从结果集的当前位置检索一行或多行
  • 可对结果集中当前位置的行进行数据修改
  • 可以显示其他用户对结果集中的数据库函数进行的数据修改

函数

触发器

特殊的存储过程,实现复杂逻辑的用户自定义约束的工具

  • 与表|视图|数据库紧密相连,不能脱离宿主存在
  • 由数据库自动调用执行,用户不能调用
  • 没有参数和返回值

Event(引起数据库更新的事件)—Condition(是否满足条件)—Action(任意的SQL)

创建:

1
CREATE trigger trigger_name BEFORE|AFTER|INSTEAD OF trigger_EVENT ON TABLE_NAME FOR EACH ROW trigger_STMT 
  • 事件
    • 表|视图级事件:insert/delete/update
    • 数据库级事件:create/alter/drop table/procedure/view
  • 触发时机:after/before/instead of(直接转到触发器动作,而不执行之前的insertupdate等操作,可以实现不可更新视图的更新
  • 触发/执行粒度:
    • 语句级触发器:缺省,每条用户语句触发一次
    • 行级触发器for each row:每条受影响的记录,触发一次触发器
  • referecing引用:包含操作的行new.attributeold.attribute
  • 动作:多于一条语句begin...end

用触发器实现级联触发:

1
create trigger fruitTrig after insert on sells referencing new row as newTuple for each row when(newTuple.fname not in (select fname from fruits)) insert into fruits(fname) values(newTuple.fname);

newTuple就是新增加的那一行

06 存储与索引

存储

逻辑组织结构

  • 块:一个磁盘页面,I/O一次读写一整个块。
  • 区:磁盘上连续的块集合。
  • 段:一个或多个盘区组成,只存储一类数据对象(表段,索引段,回滚段)一个表对应一个段
  • 表空间:数据对象的逻辑结构和物理结构统一
    • 逻辑上由0~n个段组成,物理上1~n个数据文件组成。段不能跨越表空间,但可跨越空间内文件。
    • 表空间——数据文件:一对多
  • 数据库:包含1~n个表空间(用户表空间,临时表空间…)

物理页面组织结构

索引

单级索引(二分表查找):log2nlog_2n,数量庞大时效率低

多级索引:B+树索引

如果数据量过大,树会很长,频繁磁盘I/O效率低。

  • 堆组织表:记录顺序没有限制,排列顺序不可预测(B+,Hash)
  • 索引组织表
  • 聚簇表:索引聚簇表,散列聚簇表

B树

数据库里面的数据不是一个个存储,是按页存储的。

行数据放在非叶节点中,导致页节点能放的索引项减少,树的层级增多,还是会频繁I/O。

在这里插入图片描述

B+树索引

使用最广泛,是多级索引

优点:

  • 范围查询效率更高
  • 缓存命中率更高(空间局部性原理)
  • 更新维护代价更小

特点O(logmn)O(\log_{m}n),m为分叉数

  • 数据都存储在叶结点,从树根到树叶的所有路径一样长。
  • 叶结点之间有通道可供平行查询。
  • 叶节点包含每个索引键和指向被索引行的指针(行id)

索引更新

插入删除不会引起过多I/O操作,树仍然平衡,保持了很好性能。

  • I/O密集型
  • 找到应当插入的叶节点
  • 有空间:直接插入
  • 没有空间:将该叶节点分裂成两个,使每个新节点有大于等于一半的键,并且向上直至不用再分裂

重复键的处理:用链表存储重复的键值对应的行的RID的值。

  • B+一般三层,需要三次I/O。如果根节点和中间节点存入缓存,只需1次。
  • 何时使用: 当要查询的记录数占记录总数的百分比非常大的时候,不 用索引将比用索引更快

Hash索引

只需一次I/O。

索引值通过散列函数得到的一样的值全部存储到同一个数据块中。读取是读取整个数据块到内存中,在块中顺序查找目标。

如果记录很多,可以增加一个溢出块到到桶的链上。

溢出块过多增加I/O次数!!!

特点:

  • CPU密集型
  • 等值查找时速度快
  • 不能使用范围查找
  • 不适合在重复值很多的列上建立哈希索引
  • 重构代价大,不适用更新频繁的表

聚簇索引

数据在物理文件中的存放位置不再是无序(堆组织表),根据索引中的键值逻辑顺序

  • 物理顺序只有一个,一张表只有一个聚簇索引
  • 在聚簇索引列上比B+树快
  • 重复值也排在一起,范围检查也会变快
  • 插入更新快的不用,维护开销大
  • MySQL在主键上建立

联合索引

1
Select * from tb_a where a>1 and b=1;

在(a,b)上建立,比单独建立更快。

  • 最左前缀原则:只有个使用了最左(即a),才会生效
1
select * from emp where age/2>20;

这样也不生效。

解决方法:改写为age>40

1
select  * from Emp where  to_char(birth_day,‘YYYY-MM-DD’) =2022-11-10’;

解决办法:建立函数索引to_char birth_day,'YYYY-MM-DD

分类

字段特性:主键索引(非空,一张表一个),唯一索引(unique字段上,一张表可以有多个,索引列值唯一,但可以有空值)和普通索引

查询优化

  • 选择运算尽可能先做:减少中间关系
  • 在执行连接操作前对关系适当进行预处理:按连接属性排序,在连接属性上建立索引
  • 投影运算和选择运算同时做:避免重复扫描关系
  • 将投影运算与前面或后面的双目运算结合

07 完整性约束

完整性=数据的正确性和相容性

完整性控制机制

  • 完整性约束条件定义机制
    • 完整性约束条件:数据模型的组成部分,约束数据库中数据的定义
    • DBMS提供定义数据库完整性约束条件的方法
  • 完整性检查机制:检查用户发出的操作请求是否违背了完整性约束条件
  • 违约反应:如果发现用户的操作请求使数据违背了完整性约束条件,则采取一定的动作来保证数据的完整性

完整性规则

(D,O,A,C,P)(D,O,A,C,P)

D:约束作用的数据对象

O:触发完整性检查的数据库操作

A:数据对象必须满足的断言或语义约束

C:选择A作用的数据对象值的谓词

P:违反完整性规则时触发的过程

完整性约束条件

  • 完整性约束条件作用的对象:列,元组,关系
  • 对象的两种状态:
    • 静态:对静态对象的约束是反映数据库状态合理性的约束
    • 动态:对动态对象的约束是反映数据库状态变迁的约束。涉及新值和旧值

分类

分类1

  • 静态列级约束:取值类型,取值范围,是否为空,check

    1
    alter table name add constraint name check (sex in ('男','女'));
  • 静态元组约束:元组间各个列之间的约束关系——用check实现

    1
    alter table 表名称 add constraint 约束名称 check (发货量<=订货量);
  • 静态关系约束:各个元组之间或若干关系之间存在的各种联系或约束——触发器实现

    • 职工平均工资的两倍<部门经理的工资
  • 动态列级约束:修改列定义或列值时应满足的约束条件

    • 修改列定义时的约束:原来允许空值现在不允许,数据库自动实现
    • 修改列值时的约束:新旧值之间的约束,触发器(eg:年龄只能增长)
  • 动态元组约束:修改元组值——各个字段之间要满足的约束条件

  • 动态关系约束:对关系变化前后状态的限制条件,事务一致性

分类2

  • 域完整性:自定义
  • 实体完整性约束(主键):每个元组都是可识别的唯一的。不允许无主键&主键值相同
  • 参照完整性约束(外键):外键值为空&等于所参照关系中的某个元组的主键值
  • 用户自定义约束:Check,触发器

违约反应

  • 可以拒绝执行
  • 接收操作,同时执行一些附加操作,保证数据库状态正确

删除元组

  • 级联删除(CASCADES):自动删除
  • 受限删除(RESTRICTED):没有对应的正常删除,有拒绝删除
  • 置空值删除(NULLIFILES):外码值置为空

插入元组

若被参照关系不存在响应的元组:

  • 受限插入:没有对应的拒绝插入,有对应的可插入
  • 递归插入:先向被参照关系中插入相应元组(主码值等于将要插入的外码值),再向参照关系插入

修改元组

修改主键,在参照关系中已经被引用:

  • 级联修改:对应外键全部更新
  • 受限修改:没有对应则更新,否则不更新
  • 置空值修改:对应全部置空

08 安全

数据共享必然带来数据库的安全问题

安全认证

确认试图登录数据库的用户是否被授权访问数据库的过程

数据库认证

使用存储在数据库的信息对连接到数据库的用户进行验证(常用:密码)

缺:容易被盗,难以应对复杂的网络攻击,频繁的验证操作影响性能

加强安全措施:建立密码复杂性标准,密码不包含敏感词,设置时效性

外部认证

  • 强身份认证:多因素
    • 优:根据需要选择不同身份认证机制,减少数据库管理开销
  • 代理认证:让中央设施对网络的所有成员进行身份验证
    • 优:有效解决网络上节点伪造身份,减小开销

访问控制

按照用户身份和权限,控制用户对数据库中数据访问

  • 阻止访问:无权限
  • 确定访问权限:确定主体是否有权对客体进行访问
  • 授予访问权限:授予主体对访问客体的权限
  • 撤销访问权限:删除访问权限

=+存取权限=数据对象+操作类型

分类

系统权限:

  • 启动、关闭数据库

  • 转储、恢复数据库

  • 创建、删除数据库

数据对象权限:insert,delete,update表,视图。存储过程等

列级权限

行级权限

连接级权限:连接控制

权限控制语句

授予grant,收回revoke

授予表级权限:

1
grant select on tableA on userA;

列级权限:

1
grant select (a,b) on tableA on userA;

创建新用户:

1
create user username identified by 'password';

授予登录数据库和查看数据的权利:

1
grant usage on dbname.* to username@ '%';

谁能授予、收回权限:

  • 数据对象的创建者
  • DBA
  • 拥有传播权限的用户(with grant option

授予传播权限:

注意:只能传播已经被赋予with grant option的权限,没有赋予的不能被传播!!

权限不能再传播到授权者或祖先!

1
grant select on tableA on userA with grant option;

角色

命名的权限集合,方便授权管理。角色可以基于其他角色(继承)

  • 服务器角色:系统自建,不可自建
  • 数据库角色:自建
  • public角色:所有用户都具有的权限

创建角色:

1
create role roleA;

逐个授予权限:

1
2
grant insert,delete on tableA to roleA;
grant execute on procedureA to roleA;

赋予指定用户:

1
grant roleA to userA;

09 事务管理

并发控制必须保证数据库一致性,并发控制以事务为基本单位,对事务所操作的数据施加封锁来实现一致性动态关系约束

事务:不可分割,全做&全不做,和程序两个概念, 一个对数据库进行操作的应用程序可以包含多个事务,这些事务是串行的。

用户自定义的事务以begin transaction开始,commit|rollback结束。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
BEGIN TRANSACTION
READ A
A=A-100
IF A<0
THEN
BEGIN
DISPLAY “A款不足”
ROLLBACK
END
ELSE
/* 拨款*/
BEGIN
READ B
B=B+100
DISPLAY “拨款完成”
COMMIT
ENDsql

事务:并发控制的基本单位,数据恢复的处理单位

特征ACID:

  • 原子性Atomicity:要不全做,要不全不做;保证只执行了一部分的事务不会对数据库状态产生影响
  • 隔离性Isolation:并发执行的事务不能相互影响
  • 一致性Consistency:事务完成时,所有数据都保持一致状态
  • 持久性Durability:事务一旦提交后,对数据库的影响必须是永久的

恢复机制:保证原子性和持久性

对事务的并行运行顺序合理安排:事务的隔离性和一致性

事务的并发执行

执行状态

  • 活动状态:初始
  • 部分提交状态:部分更新,但并未最后结束
  • 失败状态:无法继续进行
  • 终止状态:回滚所有操作,恢复到事务开始以前
  • 提交:正确执行

并发操作带来的数据不一致性

  • 丢失修改:事务同时修改同一数据,事务2破坏了事务1的提交

  • 不可重复读:事务1读取数据后,事务2执行更新操作,使事务1无法再现前一次读取结果。

    • 事务2更新数据
    • 事务2删除数据
    • 事务2插入一些符合事务1条件的数据(后两种叫幻影现象)
  • 读脏数据:事务2读取数据后,事务1撤销,造成事务2读入了不正确的数据

并发控制机制

调度

调度是并发运行的事务中各条指令的执行序列(应对各事务所有指令的执行时间顺序做出安排,保留原有的执行顺序)

可串行化的调度:几个事务的并行执行是正确的,当且仅当其结果与按某一次序串行地执行它们时的结果相同。

  • [x] 冲突可串行化
  • [ ] 视图可串行化

串行调度保证了数据库的一致性

冲突可串行化

只有同时读不冲突,两个指令可以随意调换位置。(调换前后——冲突等价)

前驱图

画:如果两个事务冲突,且1先访问,那么画一条1—>2的有向边,且在边上标注冲突资源

化简:如果无环—>冲突可串行,利用拓扑排序获得调度顺序

不要在最先访问处画完所有

可恢复

若事务j读取了事务i之前写入的数据,则i的提交应该早于j,以防出现回滚导致的不一致问题

无级联调度也是可恢复调

回滚

  • 级联回滚:如果失败,需要连续回滚
  • 无级联调度:可恢复调度,要求高

冲突:可串行,可恢复,最好是无级联

事务锁定使用的资源以防止其它事务访问/修改。

  • 排它锁X:写锁,对数据对象A加上X锁,则只允许T读取和修改A,其他任何事物都不能对A加任何类型锁,直到释放锁
  • 共享锁S:读锁,对数据对象A加S锁,其他事务是能对它加S锁,不能加X锁。

协议

协议内容:何时申请X|S锁,持锁时间,何时释放

一级封锁协议

修改数据就加X锁,直至事务结束;读数据不加锁:防止丢失修改,但不能保证

可重复读:不读脏数据:

二级封锁协议

写数据加X锁,读数据加S锁,读完即可释放:保证丢失修改和不读脏数据,不能保证可重复读。

不读脏数据:

不能保证可重复读:

三级封锁协议

修改数据加X锁,读取数据之前加S锁,直至事务结束才释放:可防止丢失修改、读脏数据和不可重复读。

事务隔离级别
  • 读未提交:事务A未提交所做的修改也会对事务B的查询有影响——1级
  • 读已提交:事务提交才会产生影响——2级协议
  • 可重复读:当两个事务同时进行时,其中一个事务修改数据对另一个事务不会造成影响, 即使修改的事务已经提交也不会对另一个事务造成影响——低于3级
  • 串行化:两个事务同时进行,即使读取数据也会被锁定,不能被别的事务修改——3级

两阶段封锁协议2PL

不能解决死锁问题

能够保证并发执行结果正确性的封锁协议

可解决所有数据不一致问题!!! 能够保证并发执行结果正确性:获得封锁——释放封锁

  • 在对任何数据进行读、写操作之前,事务首先要获得对该数据的封锁
  • 在释放一个封锁之后,事务不再获得任何其他封锁

对一组遵守两段锁协议的事务,可以实现可串行化调度,使得其并行执行的结果一定是正确的。但可串行化的调度中,不一定所有事物都必须符合两段锁协议

丢失更新:

不可重复读:

脏读:

不能解决级联回滚和死锁

严格的两段锁协议

增加规则:事务获得的锁只有在事务结束时才释放

第三级封锁协议与严格的两阶段锁协议一致

死锁

预防

破坏死锁产生条件

一次封锁法:一次性将所有要使用的数据全部加锁

诊断与解除

  • 允许死锁发生
  • 解决死锁
    • 由DBMS的并发控制子系统定期检测系统中是否存在死锁
    • 一旦检测到死锁,就要设法接触
  • 等待图法检测死锁

10 备份与恢复

分类

逻辑备份恢复

  • 利用sql从数据库提取数据,存入文件。可重新导入数据库中。
  • DBMS提供的导出&导入实现
  • 备份效率低,影响数据库性能(适用于小型数据库)

物理备份恢复

  • 基于数据文件和日志文件的备份恢复
  • 效率高,对数据库运行性能影响小
  • 备份策略复杂

恢复技术是系统安全性的重要保证,保证事务的原子性和持久性

  • 原子性:事务操作全做&全不做
  • 持久性:已提交事务对数据库影响是持久的,未提交事务对数据库没有影响

缓冲区处理策略

  • Force:内存中数据最晚在commit时写入磁盘
  • No Force:内存数据一直保留,commit之后过一段时间写入磁盘(崩溃还没写入,没能持久化)
  • No Steal:不允许在commit之前写入磁盘
  • Steal:允许在commit之前写入磁盘

最常使用No Force+Steal策略

No Steal+Force

只能在commit时写入。

恢复实现的技术

故障分类

事务故障

某个事务在运行过程中未运行至正常终止点就夭折(输入数据有误、运算溢出…)只影响故障事务 (程序)本身

恢复

撤销事务(UNDO):对未提交事务进行强行回滚,清除该事务对数据库的所有修改,消除未提交事务的影响。

系统故障

正常运行突然被破坏,所有正在运行的事务都非正常终止,缓冲区信息全部丢失(OS&DBMS代码错误,硬件错误,停电…)影响到当前正在运行的事务或部分已经运行完结的事务

恢复

  • 清除尚未完成的事务对数据库的所有修改:重新启动时,恢复程序强行撤销(UNDO)所有未完成事务
  • 将缓冲区已完成事务提交的结果写入数据库:恢复程序需要重做(REDO)所有已提交的事务
  • 日志文件帮助

介质故障

外存数据丢失,破坏性大(磁盘破坏,磁头碰撞…)影响到内存中的数据和磁盘上的数据

恢复

  • 装入数据库发生介质故障前某个时刻的数据副本
  • 重做自此时始所有成功事务,将这些事务已提交的结果重新计入数据库
  • 需要备份数据和日志文件的帮助

恢复技术

冗余

数据转储

整个数据库复制到磁带或者另一个磁盘上保存起来。

  • 静态转储:无运行事务时进行转储,转储期间不允许改动数据库。实现简单;但降低了可用性。

  • 动态转储:允许转储和用户事务并发运行。优点:不用等待事务结束,也不影响新事务运行;不能保证副本的数据有效。要把转储期间的修改活动登记,建立日志文件。恢复时需要日志文件+后备副本。

  • 全量存储(海量):每次转储全部数据文件。

  • 增量转储:只转储上次转储后更新过的数据(策略复杂,备份时对数据库影响小)。

登录日志文件

登记日志文件(记录事务对数据库的更新操作的文件):顺序写入效率高,先写日志文件,再写数据缓冲区,再写入数据文件(便于回退)

文件内容:

  • 事务开始标记:begin transaction
  • 结束标记:commit|rollback
  • 更新操作
  • 事务有关的内部更新操作

作用:发生系统故障,已提交事务重做Redo,未提交撤销Undo

不同模式的恢复

No Steal+Force:已提交的不受影响,未提交的自动回滚。每次事务都要进行磁盘随机写入,但性能很差。

No Steal+No Force:未提交自动回滚,已提交可能还没写到数据文件,日志文件和数据文件不一致(引入Redo日志文件,解决内存数据丢失)

Steal+Force:已提交没有影响,未提交可能被持久化到数据文件,日志文件与数据文件不一致(引入Undo日志文件,清除数据文件中未提交数据)

Steal+No Force:未提交可能被持久化到数据文件,已提交可能还没写到数据文件。(Redo,Undo,Redo/Undo)

恢复策略

基于Undo日志的恢复策略

内容

<start t>事务开始,<commit t>事务提交,<abort t>事务被回滚,<t,x,v>t事务已经更新数据项x,其更新前的旧值是v。

规则
  1. 如果事务T更新了数据项X,则日志记录<T,X,v>必须在X被写入磁盘之前写入磁盘。
  2. 如果事务T提交,则日志记录必须在T所做的所有更改写入数据文件后才能写入日志文件

更新:日志先写;提交:日志后写

恢复思路
  • 从日志文件纬度读取日志记录
  • 读到commit|abort标记T为结束状态
  • 读到<T,X,v>如果不是结束状态,就将X=v写入磁盘数据文件

恢复的每种操作都是幂等的:执行一次或多次结果相同,意味着多次遇到系统故障,重新启动即可恢复,不会影响系统数据

基于Redo日志的恢复策略

内容

<start t>事务开始,<commit t>事务提交,<abort t>事务被回滚,<t,x,v>t事务已经更新数据项x,其更新前的新值是v。

规则

更新和commit:日志文件先写

恢复思路
  • 查看redo日志,确定事务T是否完成
  • 从日志开头读取日志记录,对于每一个已完成的事务,对它进行重做操作
与Undo的比较

Undo:事务结束先对磁盘进行数据文件写入,性能较差;事务故障时回滚恢复旧值,保证原子性

Redo:可以延后写入数据文件,将已提交的重做,保证持久性,但是不允许steal,灵活性差

基于Undo/Redo的日志恢复策略

内容

<start t>事务开始,<commit t>事务提交,<abort t>事务被回滚,<t,x,u,v>t事务已经更新数据项x,其更新前的新值是v,旧值是u。

规则

更新:日志文件先写;commit随意

恢复思路
  • 确定各个事务是否已经完成
  • 从日志开头读取,已完成的事务Redo;没提交的事务Undo

基于检查点的恢复策略

在日志文件中增加检查点,增加一个“重新开始文件”作为日志文件维护状况,最新检查点作为下次恢复工作的起点

检查点记录内容:

  • 建立检查点时刻所有正在执行的事务清单
  • 这些事务最近一个日志记录的地址

重新开始文件:记录各个检查点记录在日志文件中的地址

11 关系数据理论

关系数据库的规范化理论包括三个方面的内容:函数依赖(核心),范式(模式分解的标准),模式分解

根据教学管理数据库例子:

  • 数据冗余:系名和系主任名字重复存储
  • 插入异常:新开设的系没有学生,无法存入数据库
  • 删除异常:该系所有学生毕业,系仍然存在,但找不到系的信息
  • 更新异常:学生改名,系主任更改

分解关系模式:学生,选课,系

好的关系模式:尽可能少的数据冗余,没有插入异常、删除异常、更新异常

函数依赖

关系模式中的各属性之间相互依赖、相互制约的联系称为数据依赖:分为函数依赖、多值依赖和连接依赖。

eg:给出SNO,由于一个学生只能属于一个系,则SN(姓名),AGE,DEPT(系名称)都能被唯一确定,类似于F(x)关系。这里说(SN,AGE,DEPT)函数依赖于SNO。

定义:

设关系模式R(U,F),U是属性全集,F是U上的函数依赖集,X和Y是U的子集,如果对于R(U)的任意一个可能的关系r,对于X的每一个具体值,Y都有唯一的具体值与之对应,则称X决定函数Y,或Y函数依赖于X,记作X→Y。我们称X为决定因素,Y为依赖因素。当Y不函数依赖于X时,记作:X ⇸Y。当X→Y且Y→X时,则记作:X↔︎Y。

(SNO,CNO)→SCORE,学号+班级号唯一确定成绩

说明

平凡&非平凡

  • 平凡的函数依赖:Y是X的子集,(SNO,CNO)→SNO
  • 非平凡的:Y不是X的子集,通常讨论

函数依赖是语义范畴的概念

  • 要先设定学生不存在重名,SN(学生姓名)→AGE才能成立

反应了语义完整性约束

函数依赖的存在与时间无关

  • 所有元组都应该满足约束条件
  • 元组的增加、删除或更新都不能破坏这种函数依赖

函数依赖可以保证关系分解的无损连接性

分类

  • 完全函数依赖:设 X,YX,Y 是关系 RR 的两个属性集合,如果 XYX\rightarrow Y,并且对于XX 的任何一个真子集XX',都有X!YX'!\rightarrow Y,则称 YYXX 完全函数依赖。
    • C可以通过AB得到,并且C不可以仅通过A得到,也不可以仅通过B得到,那么就说C完全依赖AB。
  • 部分函数依赖:对XX 的某个真子集XX',有XYX'\rightarrow Y,则称 YY 对部分函数依赖。
    • C可以通过AB得到,并且C也可以仅通过A得到,仅通过B得到,那么就说C部分依赖AB。
  • 传递函数依赖:设X,Y,ZX,Y,Z是关系 RR 中互不相同的属性集合,存在XY(Y!X),YZX→Y(Y !→X),Y→Z,则称 ZZ 传递函数依赖于XX
    • B可以通过A得到,C可以通过B得到,那么就称C传递依赖A。

定义候选键

KfUK\rightarrow^f U(即完全函数依赖),称K为R的一个候选键。如果有多个候选键,选定一个作为主键。

K是R的一个候选键,且SKS⊃K,S是R的超键。

候选键中出现过的为主属性,主属性外的为非主属性。

定义外键

关系模式R 中属性或属性组X 并非R 的候选键,但X 是另一个关系模式的候选键,则称X 是R 的外键。

范式

把关系数据库的规范化过程中为不同程度的规范化要求设立的不同标准称为范式。

1NF2NF3NFBCNF4NF5NF1NF\supset2NF\supset3NF\supset BCNF\supset4NF\supset5NF

一级比一级有更严格的要求。

1NF

关系中每个属性都是不可再分的简单项。排除了多值属性,组合属性。

错误示例:

既存在完全函数依赖,又存在部分函数依赖和传递函数依赖。

解决:用投影运算将关系分解,去掉过于复杂的函数依赖关系,向更高一级的范式进行转换。

2NF

每个非主属性都完全函数依赖于R的每个关系键。

解释:数据表里的每一条数据记录,都是可唯一标识的。而且所有非主键字段,都必须完全依赖主键,不能只依赖主键的一部分。

  • 从1NF关系中消除非主属性对关系键的部分函数依赖,可得到2NF
  • 如果R的关系键为单属性,或R的全体属性均为主属性,则R2NFR\in2NF

规范化—投影分解

选课表:SC(Sid,Sname,Department,Chairman,Lname,Score)

其中,姓名,系名,系主任由学号唯一确定。

所以拆分成两个表:

选课(学号,课名,分数);学生(学号,姓名,系名,系主任)。

问题:

  • 数据冗余:系名和系主任存储次数等于该系学生人数。
  • 插入异常:系没有学生无法插入。
  • 删除异常:某系学生全部毕业,系的相关信息也删除。
  • 更新异常:更换系主任,需要较多改动学生记录。

原因:存在着非主属性对主键的传递依赖。

3NF

R2NFR\in2NF,且每个非主属性都不传递依赖于R的每个关系键。

学号\rightarrow系名,系名\rightarrow系主任。

所以拆分为:

选课(学号,课名,分数);学生(学号,姓名,系名);系(系名,系主任)。

Q:所存在的异常现象已经全部消失。规范化的重点?

A:只限制了非主属性对键的依赖关系,而没有限制主属性对键的依赖关系。还可能出现异常。

SNC(SNO,SN,CNO,SCORE)假设没有重名,有两个候选键(SNO,CNO)和(SN,CNO)。

BCNF

消除任何属性(主属性或非主属性)对键的部分函数依赖和传递函数依赖。

规范化

规范化步骤

非规范化设计

  • 大量频繁的查询过程所涉及的表都需要进行连接
  • 主要的应用程序在执行时要将表连接起来查询
  • 对数据的计算需要临时表或进行复杂的查询

需要维护,占用更多磁盘空间

增加冗余列

检索一门课的任课教师姓名,class和teacher连接——在class表中增加teacher_name

增加派生列

增加的列来自其他表中的数据,由它们计算生成。

减少连接操作,避免使用集函数。

重新组表

需要查看两个表连接起来的结果数据

分库分表
  • 水平分割:一列或多列数据的值把数据行放到两个独立的表中
  • 垂直分割:把主键和一些列放到一个表,然后把主键和另外的列放到 另一个表中(查询所有数据需要join)

模式分解

在这些分解方法中,只有能够保证分解后的关系模式与原关系模式等价的方法才是有意义的

数据依赖的公理系统

逻辑蕴含:对于满足一组函数依赖F 的关系模式R ,其任何一个关系r,若函数依赖X→Y都成立, 则称F 逻辑蕴含X →Y

R<U,F>: U = {A,B,C} F={A->B,B->C}
则有,F逻辑蕴含A->B,AB->B,A->C

理由是:A->B是在F函数依赖集里面显式给出的,AB->B B属性式AB的一个子集,所以AB必然决定B, A->C则是通过函数依赖传递得到的。

Armstrong公理系统

一套推理规则,是模式分解算法理论基础。

用于:

  • 从一组函数依赖求得蕴含的函数依赖。
  • 求给定关系模式的候选键。
  • 自反律:若YXUY\subseteq X\subseteq U,则XYX\rightarrow Y为F所蕴含。
    • X包含Y,即Y是X的子集,所以必然有X决定Y。平凡的函数依赖
  • 增广律:若XYX\rightarrow Y为F所蕴含,且ZUZ\subseteq U,则XZYZXZ\rightarrow YZ为F所蕴含。
    • 可以在函数依赖两边加一样的属性
  • 传递律:若XYX\rightarrow YYZY\rightarrow Z为F所蕴含,则XZX\rightarrow Z为F所蕴含。

推论:

  1. 合并规则:由X→Y,X→Z,有X→YZ
  2. 伪传递规则:由X→Y,WY→Z,有XW→Z。
  3. 分解规则:由X→Y及 Z含于Y,有X→Z。

函数依赖闭包

在关系模式R中为F所逻辑蕴含的函数依赖的全体叫作F的闭包,记为F+。

函数依赖的闭包指F所逻辑蕴含的所有成立的函数依赖,而对于平凡函数依赖(如 (A,B)—>A )都被F所逻辑蕴含,即便F是一个空集,其闭包也包含很多函数依赖
在这里插入图片描述

属性集的闭包

设F为属性集U上的一组函数依赖,XUX\subseteq U, 则XF+={AXAX_F^+ =\{ A | X→A能由F 根据Armstrong公理导出} XF+X_F^+称为属性集X关于函数依赖集F 的闭包。

在这里插入图片描述

它将函数依赖是否成立 转化为 属性集闭包的问题

求属性集X(XU)X(X\subseteq U)关于U上的函数依赖集F的闭包XF+X_F^+的算法:

  • 输入:X,F
  • 输出:XF+X_F^+

步骤:

  • X(0)=X,i=0X(0)=X,i=0
  • 求B,这里B=\{A|(\exist V)(\exist W)(V\rightarrow W\in F\and V\subseteq X(i)\and A\in W\}
  • X(i+1)=BX(i)X(i+1)=B\cup X(i)
  • 判断X(i+1)=X(i)X(i+1)=X(i)吗?
  • 相等或X(i)=UX(i)=U,则X(i)X(i)就是XF+X_F^+,算法终止。
  • 否则i++i++

最小依赖集

函数依赖集等价G+=F+G^+=F^+,F覆盖G,或F与G等价。

充分必要条件:FG+,GF+F\subseteq G^+,G\subseteq F^+

逐一对F中的函数依赖XYX\rightarrow Y,考察Y是否属于XG++X_{G+}^+即可。

最小依赖集

  • F中任一函数依赖的右部仅含有一个属性。
  • F中不存在这样的函数依赖XAX\rightarrow A,使得F与F{XA}F-\{X\rightarrow A\}等价。
  • F中不存在这样的函数依赖XAX\rightarrow A,X有真子集Z使得F{XA}ZAF-\{X\rightarrow A\}\cup {Z\rightarrow A}与F等价。

最小依赖集构造方法

  • 逐一检查F中各函数依赖FDi:XYFD_i:X\rightarrow Y,若Y=A1A2...Ak,k>2Y=A_1A_2...A_k,k>2,则用{XAjj=1,2,...,k}\{X\rightarrow A_j|j=1,2,...,k\}来取代XYX\rightarrow Y
  • 逐一检查F中各函数依赖FDi:XAFD_i:X\rightarrow A,令G=f{xA}G=f-\{x\rightarrow A\},若AXG+A\in X_G^+,则从F中去掉此函数依赖
  • 逐一检查F中各函数依赖FDi:XAFD_i:X\rightarrow A,设X=B1B2...BmX=B_1B_2...B_m,逐一考察BiB_i,若A(XBi)F+A\in(X-B_i)_{F^+},则以XBiX-B_i取代X

模式分解的判定依据

无损连接性

分解前与分解后自然连接的结果相等。保证不丢失信息。

不一定能解决插入异常、删除异常等问题

列表法

数据库手把手解题——1.判断无损连接_数据库无损连接的判断-CSDN博客

定理法

适合关系模式R分解为两个关系模式R1、R2的

若关系模式R<U,F>中,被分解为ρ={R1<U1,F1>,R2<U2,F2>}\rho=\{R_1<U_1,F_1>,R_2<U_2,F_2>\}是R的一个分解,若R1R2R1R2R_1\cap R_2\rightarrow R_1-R_2或者R1R2R2R1R_1\cap R_2\rightarrow R_2-R_1,则具有无损连接性

一个分解具有无损连接性,能够保证不丢失信息。

一个分解保持了函数依赖,可以减轻或解决各种异常情况。

两者相互独立。

保持函数依赖

12 数据库设计

概述

  • 静态的数据库结构设计:根据给定的应用环境,进行数据库的模式的设计
    • 直观设计法:缺乏理论依据
    • 规范设计法:需求分析,概念设计,逻辑设计,物理设计
  • 动态的数据库行为设计

需求分析

重点是调查、收集与分析用户在数据管理中的:

  • 信息要求
  • 处理要求:响应时间,处理方式
  • 安全性和完整性要求:形成需求文档

分析和表达用户的需求的常用方法:

  • 自顶向下的结构化分析方法(SA):数据流图和数据字典
  • 面向对象的分析方法

数据流图

用特定的符号反映系统的数据传递和变换过程的图。

组成:数据流\rightarrow,处理(椭圆),数据存储(=),实体(□)

数据字典

进行详细的数据收集和数据分析所获得主要结果

组成:

  • 数据项
  • 数据结构
  • 数据流
  • 数据存储
  • 处理过程

概念结构设计

ER图

逻辑结构设计

由ER图向关系模型转换

设计用户子模式(定义视图)

13 NoSQL与云数据库

分布式数据库

起源—BigTable

解决google的大规模网页搜索问题

  • 底层数据存储:GFS
  • 处理海量数据:利用谷歌提出的MapReduce分布式并行计算模型
  • 协同服务管理:采用Chubby所提供的能力
  • 可扩展能力:数据到PB级、机器达上千台

HBase概述

BigTable开源实现:目标是处理非常庞大的表。

  • 解决大规模数据的离线批量处理问题
  • 克服了RDB面对大规模数据时系统扩展性和性能差问题
  • 克服了RDB难于处理非结构化与半结构化数据的缺陷

数据模型:

NoSQL非关系型数据库

  • 灵活的可扩展性
  • 灵活的数据模型
  • 与云计算紧密结合

NoSQL技术特点

  • 键值数据库:键值对。键是字符串对象,值是任意类型。

    • 优:扩展性好,灵活性好,大量写操作时性能高。
    • 缺:无法存储结构化信息,条件查询效率低。不适用通过值而非键来查
  • 列族数据库:分布式数据存储与管理

    • 优:查找速度快,可扩展性强,容易进行分布式扩展,复杂性低
    • 低:功能较少,不支持强事务一致性
    • 不适用需要ACID事务支持的情形
  • 文档数据库:用于存储并检索文档数据,可以基于文档内容构建索引(区别于键值数据库)

    • 优:数据不规则,数据迁移容易,ACID保证,读写速度快
    • 缺:缺乏统一的查询语法
  • 图形数据库:图结构,专门用于处理具有高度相互关联关系的数据

    • 优:灵活性高,支持复杂的图形算法
    • 缺:复杂性高,只能支持一定的数据规模
  • 搜索数据库:

  • 时序数据库:

NoSQL三大基石

最终一致性,CAP,BASE

CAP

  • Consistency一致性:任何一个读操作总能读到之前完成的写操作的结果
  • Availability可用性:快速获取数据,不管成功失败都有响应
  • Tolerance of Network Partition分区容忍性:当出现网络分区情况时,分离的系统也能够正常运行

一个分布式系统最多只能同时满足其两个

  • CA:把所有与事务相关的内容都放到同一台机器上(传统关系数据库),延展性差
  • CP:当出现网络分区的情况时,受影响的服务需要等待数据一致,在等待期间无法对外提供服务
  • AP:允许系统返回不一致的数据

BASE

  • 基本可用:允许分区失败的情形出现
  • 软状态:可以有一段时间不同步,有一定的滞后性
  • 最终一致性(弱一致性的一种特例):允许暂时读不到更新后的数据,但是经过一段时间后,必须最终读到更新后的数据

云数据库

部署和虚拟化在云计算环境中的数据库

Final

选择

概论

DB,DBMS,DBA,DBS

  • DB数据库:按一定结构组织并长期存储在计算机内的、可共享的大量数据的有机集合。
  • DBMS数据库管理系统:是管理和维护数据库的系统软件。MySQL,Oracle
  • DBA管理操作数据库人员
  • DBS数据库系统:基于数据库建立的一种信息系统,通常由应用程序、数据库DB、数据库管理系统DBMS和用户组成

与文件系统比较

  • 数据冗余度大;一个文件对应一个应用程序,数据不能共享
  • 数据独立性低:一旦改变数据的逻辑结构,必须修改相应的应用程序
  • 数据的一致性差

问答

数据库系统特点

  • 数据结构化
  • 数据共享
  • 数据独立性
  • 方便的用户接口
  • 同一的数据管理与控制功能

存储过程优点

  • 是SQL与模块化编程的结合,能够完成复杂业务功能
  • 在创建的时候进行预编译,可以提高SQL执行效率
  • 位于数据库服务器上,调用的时候无需通过网络传输大量数据
  • 可以作为一种安全机制来加以充分利用,例如参数化的存储过程可以防止SQL注入式攻击

游标的主要功能

  • 定位到结果集中的指定行
  • 从结果集的当前位置检索一行或多行
  • 可对结果集中当前位置的行进行数据修改
  • 可以显示其他用户对结果集中的数据库函数进行的数据修改

ORM

在关系型数据库和对象之间做映射。在操作数据库时不需要SQL,直接像操作对象一样操作它。

  • 提高开发效率
  • 数据库平台透明
  • 数据库结构自动维护
  • 代码可读性高

数据库设计(新奥尔良法)基本步骤

  • 需求分析阶段 :准确了解与分析用户需求
  • 概念结构设计阶段 :对用户需求进行综合、归纳与抽象,形成一个独立于具体DBMS的概念模型
  • 逻辑结构设计阶段 :将概念结构转换为某个DBMS所支持的数据模型
  • 物理结构设计阶段 :为逻辑数据模型选取一个最适合应用环境的物理结构
  • 数据库实施阶段:运用DBMS提供的数据语言、工具及宿主语言,根据逻辑设计和物理设计的结果
  • 数据库运行和维护阶段:经过试运行后即可投入正式运行

视图

作用:

  • 简化用户的操作
  • 使用户能以多种角度看待同一数据
  • 对重构数据库提供了一定程度的逻辑独立性
  • 对机密数据提供安全保护

触发器

触发器主要是通过事件进行触发而被执行的,而存储过程可以通过存储过程名字而被直接调用。

作用:

  • 强化约束:触发器能够实现比CHECK 语句更为复杂的约束。
  • 跟踪变化:触发器可以侦测数据库内的操作,从而不允许数据库中未经许可的指定更新和变化。
  • 级联运行:触发器可以侦测数据库内的操作,并自动地级联影响整个数据库的各项内容。例如,某个表上的触发器中包含有对另外一个表的数据操作(如删除,更新,插入)而该操作又导致该表上触发器被触发。
  • 存储过程的调用:为了响应数据库更新,触发器可以调用一个或多个存储过程,甚至可以通过外部过程的调用而在DBMS( 数据库管理系统)本身之外进行操作。

大题

关系代数

相同属性连接直接自然连接——\bowtie

不同属性连接用笛卡尔积+判断条件——σ(a.num=b.boss)(A×B)\sigma(a.num=b.boss)(A\times B)

至少|所有类问题

记得用除(就是选择符合被除属性的其余属性项)!!

  1. 查询选了所有课程的学生姓名

    SNAME(CNO,SNO(SC)÷CNO(C))(S)\prod_{SNAME}(\prod_{CNO,SNO}(SC)÷\prod_{CNO}(C))\bowtie(S)

查找教的学生的成绩都大于60分的教师(给出教师号即可):

TNO(SC)TNO(σscore<=60(SC))\prod_{TNO}(SC)-\prod_{TNO}(\sigma_{score<=60}(SC))

查找张三的直属领导和直属下级的员工编号:

num(σ((e1.boss=e2.num or e1.num=e2.boss) and name=)(emp1×emp2)\prod_{num}(\sigma((e1.boss=e2.num\ or\ e1.num=e2.boss)\ and\ name='张三')(emp1\times emp2)

SQL

默认是保留重复的行(ALL),消除取值重复的行DISTINCT

作用范围是所有目标列,写一个就好!!!

1
select distinct sno from sc;

ASC升序,DESC降序

相关子查询

查询员工中工资大于本部门平均工资的员工的name, salary和department_id

1
select name,salary,deparment_id from e1 where salary>(select avg(salary) from employees e2 where department_id=e1.department_id);

查询选修了全部课程的学生姓名:

理解为查询一个人的姓名,这个人不存在课程没有选择。

1.拿出student表中的一行数据

2.拿出课程表的一行数据

3.拿出sc表的一行数据,对比判断是否选择了

1
select sname from student where not exists(select * course where not exists (select * from sc where sc.sno=student.sno and sc.cno=c.cno));

或者直接查询选择的课程数是否等于全部课程数:

1
select sname,sno from s,sc where s.sno=sc.sno group by sno having count(*)=select count(*) from c;

最多最少问题

  • 使用ALL,ANY
  • 通过子查询比较

查询被单个学生重修次数最多的课程号、课程名、教师名:

1
select cno from sc group by sno,cno having count(*)>=all(select count(*) from sc group by sno,cno having count(*)>1);

查询员工平均薪资最高的部门(可能有多个):

1
select dept from emp e1 group by dept having avg(salary)>=all(select avg(salary) from emp e2 group by dept);

DML

创建表:

1
2
3
4
5
create table table_name(
sid varchar(20) primary key,
sname varchar(20) not null,
count int
);

insert:

1
2
insert into table_name(sid,sname,count) 
select s.sid as sid,s.sname as sname,count(sc.cid) as count from s,sc where s.sid=sc.sid group by sid;

将学生的重修课程成绩都改成60分:

1
update sc s1 set score=60 where stime>(select min(stime) from sc s2 where s1.sno=s2.sno and s1.cno=s2.cno);

视图

1
2
3
4
create view view_name[列名1,列名2,列名3]
as
子查询
[with check option];

with check option:透过视图进行增删改操作时,不得破坏视图定义中的谓词条件(即子查询中的条件表达式)

eg:

创建一个视图,列出每个比同类别商品平均价格高的商品的ID、名称、价格、部门平均价格。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
CREATE VIEW 高于平均价格的商品视图 AS
SELECT
商品.商品ID,
商品.名称,
商品.价格,
商品.类别,
AVG(同类别商品.价格) AS 平均价格
FROM
商品
JOIN
商品 AS 同类别商品 ON 商品.类别 = 同类别商品.类别
GROUP BY
商品.商品ID, 商品.名称, 商品.价格, 商品.类别
HAVING
商品.价格 > AVG(同类别商品.价格);

事务管理

前驱图检查冲突可串行性

冲突:读—写,写—写

不要在最先访问处画完所有

化简:如果无环—>冲突可串行,利用拓扑排序获得调度顺序

两段锁协议

  • 两段锁2PL:所有的数据库操作有可能会要求加锁,并且释放锁。这一切都发生在事务内部。
  • 严格两段锁:必须要等到事务完成(提交|回滚)才能释放锁。

备份与恢复

级联回滚:某些事务用到了回滚的事务修改的数据。

Undo

更新:日志先写;提交:日志后写

解决Steal+Force,未提交事务提早写入磁盘,已提交事务一定写入磁盘。

恢复:回滚未提交事务

  • 从日志文件纬度读取日志记录
  • 读到commit|abort标记T为结束状态
  • 读到<T,X,v>如果不是结束状态,就将X=v写入磁盘数据文件

Redo

更新和commit:日志文件先写

解决No Steal+No Force,已经提交事务可能没有写入磁盘,未提交的一定没有写入磁盘。

恢复:重做已提交的事务

  • 查看redo日志,确定事务T是否完成
  • 从日志开头读取日志记录,对于每一个已完成的事务,对它进行重做操作

Undo/Redo

更新:日志文件先写;commit随意

解决Steal+No Force,已提交的可能没写入磁盘,未提交的可能已写入磁盘。

恢复:重做已完成的,撤销没完成的

  • 确定各个事务是否已经完成
  • 从日志开头读取,已完成的事务Redo;没提交的事务Undo

规范化理论

求闭包

求属性集X(XU)X(X\subseteq U)关于U上的函数依赖集F的闭包XF+X_F^+

先将XX放入结果,通过已有都能确定什么。

求候选键

  • LL类属性:只在FF中某个函数依赖的左部出现
  • RR:只在右出现
  • LRLR:左右都出现
  • NN:没有出现过

步骤:

  • 求解LLN,LRN,LR类属性
  • (L,N)+=U(L,N)^+=U,则(L,N)(L,N)为唯一候选键
  • 如果(L,N)+U(L,N)^+\neq U,则找LRLR
  • 遍历LRLR中的单一属性AA,如果(L,N,A)+=U(L,N,A)^+=U,则为候选键
  • 如果在上一步找到所有的候选键,则算法结束。否则遍历YY中任意两个三个属性与(L,N)(L,N)构成属性组,如果新属性组不包含已有的候选键且新属性组闭包为UU,则构成新候选键。

求最小依赖集

  • F中任一函数依赖的右部仅含有一个属性。删去重复,AC,ABCA\rightarrow C,AB\rightarrow C。后者多于
  • F中不存在这样的函数依赖XAX\rightarrow A,使得F与F{XA}F-\{X\rightarrow A\}等价。
  • F中不存在这样的函数依赖XAX\rightarrow A,X有真子集Z使得F{XA}ZAF-\{X\rightarrow A\}\cup {Z\rightarrow A}与F等价。

分解到3NF

保持依赖分解法
  • FF的最小依赖集
  • 将最小依赖集中不出现的组成一个关系模式
  • 将左部相同的所有函数依赖合并组成新关系

既保持依赖,又无损分解
  • 先求出分解到3NF保持函数依赖分解
  • 求候选键,也算是一个分解
  • 如果有UiXU_i\subseteq X,则将UiU_iσ\sigma中去掉。

分解到BCNF

无法保证保持所有函数依赖,但保证无损连接分解

  • 求候选码

  • 逐个考察函数依赖

  • 看能不能再分解

R(ABCDEG) F=(AB,BC,ADG,DEA\rightarrow B,B\rightarrow C,AD\rightarrow G,D\rightarrow E)

  1. 码为AD
  2. 分解,重新考察函数依赖(只放在有字母的里面,传递依赖也要考虑完全!!!):AB(AB)AB(A\rightarrow B) ACDEG(ADG,DE,ACAD\rightarrow G,D\rightarrow E,A\rightarrow C)
  3. 只有两个的肯定是BCNF,不是的要考虑继续分解
  4. ACDEG(ADG,DE,ACAD\rightarrow G,D\rightarrow E,A\rightarrow C)的码为AD,码要重新求
  5. 分解DED\rightarrow E为:DE(DED\rightarrow E) ACDG(ADG,ACAD\rightarrow G,A\rightarrow C)
  6. 重新求码为AD,ACA\rightarrow C不满足,所以要重新分解
  7. 分解为:AC(ACA\rightarrow C) ADG(ADGAD\rightarrow G)
  8. 最终分解为:AB,DE,AC,ADG

判断是否保持函数依赖

直观感知:从几个分解中寻找函数依赖,看这几个函数依赖能否推出剩下的函数依赖

  • 由分解找到所有的函数依赖(求闭包确定所有的别落下)并在一起为G
  • 看缺哪个函数依赖
  • 在G中推不在的函数依赖的闭包,如果不存在则满足函数依赖

判断无损连接

列表法证明。

  • 每个分解占一行,是则为aia_i,不是则为bijb_{ij}
  • 逐个函数依赖,比如ADA\rightarrow D,如果有行A,DA,D都是a,则将其他aa已知转化为b14b_{14}
  • 如果只有AAaa,那就把所有有aaDD转化为b14b_{14}
  • 如果b14b_{14}能推到a,那么其他b也都能推到a

数据库设计

🍰 实体:矩形框

🍰 属性:椭圆框并用连线连到相应实体。

🍰 联系:菱形框并用连线与有关的实体相连。

联系的元:参与联系的实体的个数。

联系的基数比约束:1:1,1:n,m:n(谁是1那边谁标1:领导1工人n)

文章作者: bubble
文章链接: http://example.com/2024/07/24/数据库/
版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 bubble's blog