数据库
第一章 绪论
基本概念
- 数据(Data)
- 数据库管理系统(DataBase Management System)
- 数据库系统(DataBase System)
数据模型
数据模型类型
- 概念层数据模型
- 分类
- 实体(Entity)
- 属性(Attribute)
- 码(Key)
- 域(Domain)
- 实体型(Entity Type)
- 实体集(Entity Set)
- 联系(Relationship)
- 概念模型的表示方法
- E-R
- 分类
- 逻辑层数据模型
- 层次模型
- 网状模型
- 关系模型(重点)
- 面向对象模型
- 物理层数据模型
三层模式结构
- 模式
- 外模式
- 内模式
第二章 关系数据库
概念
- 域(domain)
- 笛卡儿积
- 关系
- 候选码
- 主码
关系操作
- 查询
- 插入
- 删除
- 修改
关系代数
- 集合运算符
- 并
- 差
- 交
- 笛卡儿积
- 关系运算符
- 选择 σ
- 投影 Π
- 投影会取消重复的元组结果(类似于SQL中使用了Distinct)
- 连接 ∞
- θ连接
- 等值连接
- 自然连接
- 外连接
- 左连接
- 右连接
- 除 ÷
- https://blog.csdn.net/skyejy/article/details/80890842
第三章 SQL
...
SQL语言分为五大类:
- DDL(数据定义语言) - Create、Alter、Drop 这些语句自动提交,无需用Commit提交。
- DQL(数据查询语言) - Select 查询语句不存在提交问题。
- DML(数据操纵语言) - Insert、Update、Delete 这些语句需要Commit才能提交。
- DTL(事务控制语言) - Commit、Rollback 事务提交与回滚语句。
- DCL(数据控制语言) - Grant、Revoke 授予权限与回收权限语句。
第六章 关系数据理论
函数依赖
记 A->B 表示 A 函数决定 B,也可以说 B 函数依赖于 A。
如果 {A1,A2,... ,An} 是关系的一个或多个属性的集合,该集合函数决定了关系的其它所有属性并且是最小的,那么该集合就称为键码。
部分函数依赖:对于 A->B,能找到 A 的真子集 A',使得 A'-> B。部分函数依赖记作 A -P→ B。
完全函数依赖:对于 A->B,任何 A 的真子集 A',都不能使 A'-> B。完全函数依赖记作 A -F→ B。
传递函数依赖:对于 A->B,B->C,则 A->C 是一个传递函数依赖,记作 A -传递→ B。
码
表中可以唯一确定一个元组的某个属性(或者属性组)称为码
- 候选码
- 若关系中的一个属性或属性组的值能够唯一地标识一个元组,且他的真子集不能唯一的标识一个元组,则称这个属性或属性组做候选码
- 超码
- 与候选码的关系就像完全函数依赖与部分函数依赖的关系
- 主码
- 唯一标识
- 主码一定是候选码的子集
- 主属性
- 在任一候选码里出现过的属性
- 全码
- 整个表所有属性当作一个候选码
范式
高级别范式的依赖于低级别的范式,1NF 是最低级别的范式。
级别递进关系:1NF -> 2NF -> 3NF -> BCNF -> 4NF
1. 第一范式(1NF)
属性(列)不可再分。
2. 第二范式(2NF)
每个非主属性完全函数依赖于任何一个候选码。
即没有包含在主键中的列必须完全依赖于主键,而不能只依赖于主键的一部分。
即:消除非主属性对码的部分依赖
可以通过分解来满足。
3. 第三范式(3NF)
非主属性不能有传递函数依赖于键码。
即:消除非主属性对码的传递函数依赖
4. BCNF
BCNF(Boyce Codd Normal Form)通常被认为是修正的第三范式,或称扩充的第三范式。
X -> Y 且 Y 不包含于 X 时,X 必含有码。
即:消除主属性对码的部分和传递函数依赖。
多值依赖
若 A 多值依赖于 B,则 A 的一组数据同时依赖于 B 的一个值,即 B 一个值的改变会导致 A 多个值同时改变。记作 A ->-> B。
函数依赖可以认为是多值依赖的一种,是特殊情况。
多值依赖被用于第四范式中。
5. 第四范式(4NF)
消除多值依赖。
准确的说是消除非平凡非函数依赖的多值依赖。
模式分解
三种定义
- 具有无损连接性
- 保持函数依赖
- 既具有无损连接性,又保持函数依赖
算法判定无损连接性的算法
未整理
输入:关系模式R(A1,A2,…,An),它的函数依赖集F以及分解={R1,R2,…,Rk}。
输出:确定是否具有无损连接性。
方法:
(1)构造一个k行n列的表,第i行对应于关系模式Ri,第j列对应于属性Aj。如Aj∈Ri,则在第i行第j列上放符号aj,否则放符号bij。
(2)逐一检查F中的每一个函数依赖,并修改表中的元素。方法:取F中一个函数依赖X→Y,在X的列中寻找相同的行,然后将这些行中Y的分量改为相同的符号,如果其中有aj,则将bij改为aj;若其中无aj,则改为某一个bij。
(3)反复检查第(2)步,至无改变为止,若存在某一行为a1,a2,…,ak,则分解具有无损连接性;如果F中所有函数依赖都不能再修改表中的内容,且没有发现这样的行,则分解不具有无损连接性。
第七章 数据库设计
需求分析
E-R模型
E-R 图即实体-关系图(Entity-Relationship),有三个组成部分:实体、属性、联系。
- 实体型用矩形表示
- 属性用椭圆形表示
- 联系用菱形表示
实体的三种联系包含一对一,一对多,多对多三种:
- 一对多:那么画个带箭头的线段由A指向B
- 一对一:画两个带箭头的线段
- 多对多:画两个不带箭头的线段
下图为一个一对多的例子:
E-R 向关系模型的转换
实体类型的转换
将每个实体类型转换成一个关系模式,实体的属性即为关系的属性,实体标识符即为关系的码。
联系类型的转换
https://blog.csdn.net/qq_41706331/article/details/91467961
实体间的联系是:
1:1
- 将1:1联系转换为一个独立的关系:与该联系相连的各实体的码以及联系本身的属性均转换为关系的属性,且每个实体的码均是该关系的候选码。
- 将1:1联系与某一端实体集所对应的关系合并,则需要在被合并关系中增加属性,其新增的属性为联系本身的属性和与联系相关的另一个实体集的码。
1:N
- 一种方法是将联系转换为一个独立的关系,其关系的属性由与该联系相连的各实体集的码以及联系本身的属性组成,而该关系的码为n端实体集的码。
- 在n端实体集中增加新属性,新属性由联系对应的1端实体集的码和联系自身的属性构成,新增属性后原关系的码不变。
M:N
- 与该联系相连的各实体集的码以及联系本身的属性均转换为关系的属性,新关系的码为两个相连实体码的组合(该码为多属性构成的组合码)。
三个及以上的实体集间的多元联系进行转换:
一对多
- 转换为关系模型的方法是修改n端实体集对应的关系,即将与联系相关的其他1端实体集的码和联系自身的属性作为新属性加入到n端实体集中。
多对多
- 转换为关系模型的方法是新建一个独立的关系,该关系的属性为多元联系相连的各实体的码以及联系本身的属性,码为各实体码的组合。
第八章 存储过程
...
第十章 事务
事务是用户定义的一个数据库操作序列,是一个不可分割的工作单位。
在SQL中,事务以BEGIN TRANSACTION
开始,以COMMIT
或ROLLBACK
结束。
MySQL默认自动提交,如果不显式使用BEGIN TRANSACTION
,则每个操作都会被当作一个事物并自动提交。
事务满足ACID特性。
ACID特性
1. 原子性(Automicity)
事务被视为不可分割的最小单元,事务的所有操作要么全部提交成功,要么全部失败回滚。
回滚可以用回滚日志(Undo Log)来实现,回滚日志记录着事务所执行的修改操作,在回滚时反向执行这些修改操作即可。
2. 一致性(Consistency)
数据库在事务执行前后都保持一致性状态。在一致性状态下,所有事务对同一个数据的读取结果都是相同的。
3. 隔离性(Isolation)
一个事务所做的修改在最终提交以前,对其它事务是不可见的。
4. 持续性(Durability)
一旦事务提交,则其所做的修改将会永远保存到数据库中。即使系统发生崩溃,事务执行的结果也不能丢失。
系统发生奔溃可以用重做日志(Redo Log)进行恢复,从而实现持久性。与回滚日志记录数据的逻辑修改不同,重做日志记录的是数据页的物理修改。
第十一章 并发控制
事务是并发控制的基本单位。
在并发环境下,事务的隔离性很难保证,因此会出现很多并发一致性问题。
并发一致性问题
1. 丢失修改
T1 和 T2 两个事务都对一个数据进行修改,T1 先修改,T2 随后修改,T2 的修改覆盖了 T1 的修改。
2. 不可重复读
T2 读取一个数据,T1 对该数据做了修改。如果 T2 再次读取这个数据,此时读取的结果和第一次读取的结果不同。
3. 读脏数据
T1 修改一个数据,T2 随后读取这个数据。如果 T1 撤销了这次修改,那么 T2 读取的数据是脏数据。
产生并发不一致性问题的主要原因是破坏了事务的隔离性,解决方法是通过并发控制来保证隔离性。并发控制可以通过封锁来实现,但是封锁操作需要用户自己控制,相当复杂。数据库管理系统提供了事务的隔离级别,让用户以一种更轻松的方式处理并发一致性问题。
并发控制主要技术
- 封锁(locking)
- 时间戳(timestamp)
- 乐观控制法(optimistic scheduler)
- 多版本并发控制(MVCC)
封锁
封锁类型
- 排他锁(Exclusive),简称X锁,又称写锁
- 共享锁(Shared),检测S锁,又称读锁
封锁协议
1. 一级封锁协议
事务 T 要修改数据 A 时必须加 X 锁,直到 T 结束才释放锁。
可以解决丢失修改问题,因为不能同时有两个事务对同一个数据进行修改,那么事务的修改就不会被覆盖。
2. 二级封锁协议
在一级的基础上,要求读取数据 A 时必须加 S 锁,读取完马上释放 S 锁。
可以解决读脏数据问题,因为如果一个事务在对数据 A 进行修改,根据 1 级封锁协议,会加 X 锁,那么就不能再加 S 锁了,也就是不会读入数据。
3. 三级封锁协议
在二级的基础上,要求读取数据 A 时必须加 S 锁,直到事务结束了才能释放 S 锁。
可以解决不可重复读的问题,因为读 A 时,其它事务不能对 A 加 X 锁,从而避免了在读的期间数据发生改变。
还有两段锁协议,放在下面介绍。
活锁与死锁
解决活锁问题
- 先来先服务策略
死锁预防
- 一次封锁法
- 顺序封锁法
死锁诊断
- 超时法
- 等待图法
并发调度的可串行性
强制事务串行执行,这样多个事务互不干扰,不会出现并发一致性问题。
该隔离级别需要加锁实现,因为要使用加锁机制保证同一时间只有一个事务执行,也就是保证事务串行执行。
两段锁协议是可串行化调度的一种实现。
两段锁协议(2PL)
加锁和解锁分为两个阶段进行。
事务遵循两段锁协议是保证可串行化调度的充分条件。例如以下操作满足两段锁协议,它是可串行化调度。
lock-x(A)...lock-s(B)...lock-s(C)...unlock(A)...unlock(C)...unlock(B)
但不是必要条件,例如以下操作不满足两段锁协议,但它还是可串行化调度。
lock-x(A)...unlock(A)...lock-s(B)...unlock(B)...lock-s(C)...unlock(C)
参考
- CyC2018 CS-Notes https://github.com/CyC2018/CS-Notes#floppy_disk-数据库