数据模型类型
...
SQL语言分为五大类:
记 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 图即实体-关系图(Entity-Relationship),有三个组成部分:实体、属性、联系。
实体的三种联系包含一对一,一对多,多对多三种:
下图为一个一对多的例子:
实体类型的转换
将每个实体类型转换成一个关系模式,实体的属性即为关系的属性,实体标识符即为关系的码。
联系类型的转换
https://blog.csdn.net/qq_41706331/article/details/91467961
实体间的联系是:
1:1
1:N
M:N
三个及以上的实体集间的多元联系进行转换:
一对多
多对多
...
事务是用户定义的一个数据库操作序列,是一个不可分割的工作单位。
在SQL中,事务以BEGIN TRANSACTION
开始,以COMMIT
或ROLLBACK
结束。
MySQL默认自动提交,如果不显式使用BEGIN TRANSACTION
,则每个操作都会被当作一个事物并自动提交。
事务满足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 读取的数据是脏数据。
产生并发不一致性问题的主要原因是破坏了事务的隔离性,解决方法是通过并发控制来保证隔离性。并发控制可以通过封锁来实现,但是封锁操作需要用户自己控制,相当复杂。数据库管理系统提供了事务的隔离级别,让用户以一种更轻松的方式处理并发一致性问题。
并发控制主要技术
封锁类型
1. 一级封锁协议
事务 T 要修改数据 A 时必须加 X 锁,直到 T 结束才释放锁。
可以解决丢失修改问题,因为不能同时有两个事务对同一个数据进行修改,那么事务的修改就不会被覆盖。
2. 二级封锁协议
在一级的基础上,要求读取数据 A 时必须加 S 锁,读取完马上释放 S 锁。
可以解决读脏数据问题,因为如果一个事务在对数据 A 进行修改,根据 1 级封锁协议,会加 X 锁,那么就不能再加 S 锁了,也就是不会读入数据。
3. 三级封锁协议
在二级的基础上,要求读取数据 A 时必须加 S 锁,直到事务结束了才能释放 S 锁。
可以解决不可重复读的问题,因为读 A 时,其它事务不能对 A 加 X 锁,从而避免了在读的期间数据发生改变。
还有两段锁协议,放在下面介绍。
解决活锁问题
死锁预防
死锁诊断
强制事务串行执行,这样多个事务互不干扰,不会出现并发一致性问题。
该隔离级别需要加锁实现,因为要使用加锁机制保证同一时间只有一个事务执行,也就是保证事务串行执行。
两段锁协议是可串行化调度的一种实现。
加锁和解锁分为两个阶段进行。
事务遵循两段锁协议是保证可串行化调度的充分条件。例如以下操作满足两段锁协议,它是可串行化调度。
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)