数据库模式
DBMS的三级模式两级结构
数据库的设计过程
ER模型
关系代数与元组演算
并,交,差,笛卡尔积(*),投影,选择,连接。
笛卡尔积(X × Y)
投影(π):选择对应的列,但是得到的结果不能有完全相同的行。
选择(σ):选择行,选择表中满足表达式对应的行。
连接(∞):将两个表中满足关系的行进行拼接 ,但是不能出现重复的列字段。假如没有条件,则称为自然连接。
自然连接:即根据两个表中的相同字段进行连接。
规范化理论
函数依赖:在一个表中,由一个属性可以确定另外一个属性
例如:在一个表中,一个学号可以唯一确定一个姓名,但是姓名不能唯一确定一个学号
部分函数依赖:通过AB能得出C,通过A也能得出C,通过B也能得出C,那么说C部分依赖于AB。
完全函数依赖:通过AB能得出C,但是AB单独得不出C,那么说C完全依赖于AB.
传递函数依赖:通过A得到B,通过B得到C,但是C得不到B,B得不到A,那么成C传递依赖于A
规范化理论的价值:减少数据冗余,更新异常,插入异常,删除异常
键
超键(超码):可以唯一标识元组的属性集——意即可以有多余的属性
学生(学号,姓名,性别,身份证号,教师编号)
教师(教师编号,姓名,工资)
学生表超键:学生表中含有学号或者身份证号的任意组合都为此表的超键,比如(学号,姓名)或者(身份证号,性别)
候选键(候选码):不包含多余属性的超键
学生表超键:学号和身份证号都可以作为候选键
主键:从候选键中任选一个来标识元组。
例如:在同一张表中,有学号和身份证号,学号或者身份证号都可以作为主键。
外键:在A表中,某属性是B表的主键,则该属性是A表的外键
如何求候选键
将关系模式中的函数依赖关系用有向图来表示。
找到入度为0的属性,并以该属性为起点,尝试遍历有向图,若能正常遍历图中所有节点,则该属性为关系模式的候选键。(入度为0,即没有箭头指向它)
若没有入度为0的属性,则尝试选择将既有入度也有出度的属性来看是否能够遍历整个图
答案:
1.A
2.ABCD
3.B
范式
背景:我们在构建数据库的时候,只需要满足数据库构建的基本要求即可,但是这样构建出来的数据库会出现很多问题。例如数据冗余,插入异常,删除异常。因此我们需要对表的结构加上一定约束,来消除这些异常,因此产生了范式。
Normal Form——一般的形式。
第一范式
在关系模式R中,每个属性都不能再细分。
第二范式
当且仅当关系模式R是1NF时,且每一个非主属性完全依赖4主键(消除部分依赖)
假如一个表不满足第二范式的结果会是什么呢?
在以上表中,(学号,课程号)共同构成组表的主键,成绩完全依赖于主键,但是姓名却部分依赖于主键,因为学号确定了,那么姓名也就确定了,并不需要课程号。(前提条件:表中属性值不允许为null。)
存在的问题:
- 由于学生的各种课程成绩都在该表中,姓名部分依赖于主键,因此姓名这个属性的值会随着各种课程成绩的加入,使得张三等学生的姓名产生大量的冗余。
- 插入异常5:新生开学的时候,由于没有选课,缺少课程号,无法插入学生信息。
- 更新异常6:若某个学生的姓名写错了,需要修改他的信息,则需要花费大量的时间
- 删除异常7
第三范式
在第二范式的基础上,且没有非主属性传递依赖于候选键(不包含传递依赖)。
[参考链接] zhuanlan.zhihu.com/p/20028672
BCF范式
在第三范式的基础上,非主属性和主属性都不能被非主属性所决定
模式分解
保持函数依赖分解
无损分解
将一个关系模式分解为若干关系模式后,通过使用自然连接或者投影等方式将这些关系模式重新整合为原来的关系模式。
如何判断是不是无损分解?
表格法
首先:将原来的关系模式中所有的属性作为表格的列,并将分解后得到的关系模式名称作为表格的行
例如有关系模式:成绩(学号,姓名,课程号,课程名,分数)
函数依赖:学号—>姓名,课程号—>课程名,(学号,课程号)—>分数
分解后的关系模式:
成绩(学号,课程号,分数)
学生(学号,姓名)
课程(课程号,课程名)
则有下表
| 学号 | 姓名 | 课程号 | 课程名 | 分数 | |
|---|---|---|---|---|---|
| 成绩 | |||||
| 学生 | |||||
| 课程 |
然后:将分解后得到的关系模式中的属性记为a,数字代表列号,不在原关系模式中的属性记为b,数字代表行号和列号。
| 学号 | 姓名 | 课程号 | 课程名 | 分数 | |
|---|---|---|---|---|---|
| 成绩 | a1 | b12 | a3 | b14 | a5 |
| 学生 | a1 | a2 | b23 | b24 | b25 |
| 课程 | b31 | b32 | a3 | a4 | b35 |
分解后得到的关系模式学生中有学号—>姓名的函数依赖,同时由于成绩的关系模式中有a1,于是将成绩的姓名列的值改为a2。
| 学号 | 姓名 | 课程号 | 课程名 | 分数 | |
|---|---|---|---|---|---|
| 成绩 | a1 | a2 | a3 | b14 | a5 |
| 学生 | a1 | a2 | b23 | b24 | b25 |
| 课程 | b31 | b32 | a3 | a4 | b35 |
同理,由于课程中有课程号—>课程名的函数依赖,且成绩中课程号,即把课程名列改为a4
| 学号 | 姓名 | 课程号 | 课程名 | 分数 | |
|---|---|---|---|---|---|
| 成绩 | a1 | a2 | a3 | a4 | a5 |
| 学生 | a1 | a2 | b23 | b24 | b25 |
| 课程 | b31 | b32 | a3 | a4 | b35 |
至此,成绩中所有列的值都为a,因此,该分解为无损分解。
并发控制
事务
为什么需要事务?
以转账操作为例
用户A向用户B转账100RMB,在用户看来只有一个操作。实际上至少会有两个步骤。
1.将A账户的金额减少100元
2.将B账户的金额增加100元
在此过程中可能会出现如下问题:
1.转账操作的第一步执行成功,A账户上的钱减少了100元,但是第二步执行失败或者未执行便发生系统崩溃,导致B账户并没有相应增加100元。
2.转账操作刚完成就发生系统崩溃,系统重启恢复时丢失了崩溃前的转账记录
3.同时又另一个用户转账给B账户,由于同时对B账户进行操作,导致B账户金额出现异常。
将多条SQL语句作为一个整体进行操作
事务的特点:
-
原子性。
即事务中所有的SQL语句要么全部执行,要么全都不执行 -
一致性。
事务必须使数据库从一个一致性状态变换到另一个一致性状态 -
隔离性。
隔离性是当多个用户并发访问数据库时,比如操作同一张表时,数据库为每一个用户开启的事务,不能被其他事务的操作所干扰,多个并发事务之间要相互隔离。 即要达到这么一种效果:对于任意两个并发的事务T1和T2,在事务T1看来,T2要么在T1开始之前就已经结束,要么在T1结束之后才开始,这样每个事务都感觉不到有其他事务在并发地执行 -
持久性。
指一个事务一旦被提交了,那么对数据库中的数据的改变就是永久性的
并发产生的问题
丢失更新
理论上最终得到A的值应该是:-3,但是实际上得到的结果确是2。
不可重复读问题
是指同一个事务对同一个数据读取结果前后不一致(事务1中读取的同一个数据前后不一致)
“脏”读
一个事务读取了另一个事务未提交的数据。事务2读取了事务1中不是最终值的脏数据(即在事务1中最后撤销了对A的值的更改)
三级封锁协议
为了解决并发操作中数据库出现的问题
除非事务获得数据上的锁,否则任何事务都不能对该数据进行读写(那一级锁能解决脏读问题啊)
S锁(shared) :事务可读不可写(其他事务可以同时添加S锁,其它事务都不能修改数据)
X锁(exclusive):事务T对数据A加X锁,只允许事务T读取和修改数据A(其他事务不可以同时添加任何锁) ——此时其它事务可以读吗?
即X锁不能与其他锁同时存在。而s锁与s锁之间可以同时存在。
一级锁协议
事务T修改数据R之前,先加X锁,直到事务结束时释放(无论是正常结束commit还是非正常结束rollback)
作用:可防止更新丢失问题。
不使用锁出现更新丢失问题(两个事务都要进行写操作)
使用一级锁解决更新丢失问题
二级锁协议
在一级封锁的基础上,事务在读取数据之前必须先对其加上S锁,读完即可释放S锁
作用:防止更新丢失问题和脏读问题。
你理解了吗?
三级锁协议
内容:在一级封锁协议的基础上,事务在读取数据之前必须先对其加S锁,直到事务结束才释放
作用:防止更新丢失,脏读和不可重复读问题。
数据库完整性约束
实体完整性约束
即主键不能为空,不能重复
参照完整性约束
即某个表中的外键,它的取值必须是正确的或者为NULL
用户自定义完整性约束
用户对表的某个属性定义的约束,例如有个年龄的属性,则可以定义年龄不能大于200且不能为负数的约束
数据库安全
| 措施 | 说明 |
|---|---|
| 用户标识和鉴定 | 最外层的安全保护措施,可以使用用户账户、口令及随机数检验等方式 |
| 存取控制 | 对用户进行授权,包括操作类型(例如:查找,插入,删除...)和数据对象(基本表,视图,索引) |
| 密码存储和传输 | 对远程终端的信息进行加密处理 |
| 视图1的保护 | 对视图进行授权(参考blogs.sap.com/2014/11/18/…) |
| 审计 | 使用专门的文件或者数据库,总动将用户的所有操作记录下来 |
数据库备份与恢复
备份:导出数据或者复制表文件的方式来制作数据库的副本。当数据库出现故障或遭到破坏时,将备份的数据库加载到系统,从而使数据库从错误状态恢复到备份时的正确状态。
冷备份:在数据库关闭的情况下,将数据库中的文件全部复制下来
热备份:利用备份软件,在数据库正常运行的状态下,将数据库中的数据文件备份出来
| 优点 | 缺点 | |
|---|---|---|
| 冷备份 | 快速(只需复制文件);容易恢复到某个时间点; | 备份过程中,数据库不能做其它工作。若磁盘空间不够,只能复制到其他外部存储设备上;不能按表或用户恢复 |
| 热备份 | 在表空间或数据库文件级备份;备份的时间短;备份时数据库仍然可用;可几乎对所有数据库实体做恢复 | 不能出错,否则后果很严重 |
完全备份:备份所有数据
差量备份:仅备份上一次完全备份之后变化的数据
增量备份:备份上一次备份之后变化的数据
数据库转储
通常以SQL语句的形式保存表结构或者表中的数据。
(1)静态海量转储:在系统中无事务时运行,每次转储全部数据库
(2)静态增量转储:在系统中无事务时运行,每次只转储上一次转储后更新过的数据
(3)动态海量转储:转储期间允许对数据库进行存取或者修改,每次转储全部数据库
(4)动态增量转储:转储期间允许对数据库进行存取或者修改,每次转储上一次转储后更新过的数据
日志文件:针对数据库改变所做的记录,可以记录针对数据库的任何操作,并将记录结果保存在独立的文件中(在对数据进行更改之前,先把操作记录下来,再进行对数据的更改)
数据库故障与恢复
| 故障类型 | 故障原因 | 解决办法 |
|---|---|---|
| 事务本身可预期的故障 | 本身逻辑 | 在程序中预先设置Rollback语句 |
| 事务本身不可预期的故障 | 算术溢出,违反完整性约束 | 由恢复子系统通过日志,撤销事务对数据库的更改,回退到事务初始状态 |
| 系统故障 | 由于各种原因导致数据库系统停止运转 | 检查点法3 //Do you understand? |
| 介质故障 | 存储在外存上的数据部分损失或全部损失 | 在新磁盘上,导入最新的数据库备份文件。根据日志文件,找出来从该最新备份后开始,到故障发生时,哪些事务已经完成。REDO(重做)所有已提交2的事务 |
数据仓库与数据挖掘
数据仓库是信息(对其进行分析可做出更明智的决策)的中央存储库。数据仓库的主要应用是为了OLAP(On-Line Analytical Processing)
反规范化理论
由于规范会会使表不断的拆分,从而使数据表过多,虽然这样减少了数据冗余,提高了增,删,改的速度,但会增加查询的工作量。因此,需要反规范化来增加查询的效率。
技术手段:
- 增加冗余列
- 重新组表
- 分割表
分布式数据库
利用计算机网络将物理上分散的多个数据库连接起来组成一个逻辑上的数据库。
DDBMS 设计者可以选择对表进行分段、复制分段并将它们存储在不同的站点。
分片透明:用户可以查询任何表,似乎该表并没有分片。它向用户掩盖了用户查询的表实际上是一个片段或者说一些片段的组合这一事实
复制透明:用户不用关心数据库在网络中各个节点的复制情况
逻辑透明:是指局部数据模型透明,即用户或者应用程序无需知道局部使用的是哪种数据模型
位置透明:位置透明度确保用户可以查询任何表或表的片段,就好像它们本地存储在用户站点中一样。 最终用户应该完全忘记表或其片段存储在分布式数据库系统中的远程站点这一事实。 远程站点的地址和访问机制是完全隐藏的。
[1] 从一个或多个表(或视图)导出的表
[2] 事务顺利执行完毕
[3]
[4] 依赖:在表R中,若两行记录在属性A上的值相等,则两个记录在属性B上的值必定相等,称B函数依赖于A。即不存在两行记录在属性A上的值相等,而两个记录在属性B上的值不相等。
[5] 当我们向表中插入新的记录时,由于记录中某个属性值为空,但是数据库不允许该值为空,则该条记录就不能插入数据库
[6] 即更改数据库中某一个属性的值时,需要在该表的其它位置进行相同的操作
[7] 当删除表中不需要的信息的同时,会删除其它一些需要的信息