🚀 Database
1、数据库基础
1.1 事务的概念和特性
1.2 锁
1.3 锁协议
1.4 事务日志
1.5 MVCC实现原理
1.6 基础知识
1.6.1 三范式
1.6.2 多表连接方式
1.6.3 存储过程
1.6.4 TRUNCATE和DROP的区别
1.6.5 触发器
1.6.6 视图
2、MySQL
2.1 索引
2.2 索引组织表
2.3 InnoDB和MyISAM的区别
2.4 Checkpoint技术
2.5 宕机恢复原理
2.6 数据库优化
2.7 分库分表
2.8 一致性哈希算法
2.9 主从复制
3、Redis
3.1 概述
3.1.1 为什么Redis单线程还这么快
3.1.2 Redis数据类型
3.1.3 持久化机制
3.1.4 过期机制和内存淘汰策略
3.2 线程模型
3.3 分布式问题
3.3.1 Redis实现分布式锁
3.4 缓存异常
3.4.1 缓存击穿、缓存雪崩
3.5 高可用
3.5.1 主从复制
3.5.2 哨兵模式
3.5.3 集群模式
-
+
游客
注册
登录
三范式
数据库的设计范式是数据库设计所需要满足的规范,满足这些规范的数据库是**简洁**的、**结构明确**的,同时**不会发生插入**(`insert`)、**删除**(`delete`)、和**更新(**`update`)**操作异常**。 ## 1 第一范式(1NF) ### 1.1 含义 1. 符合 1NF 的关系中**每个属性都不可再分**。 2. 1NF 是**所有关系型数据库的最基本要求**。 ### 1.2 示例 1. 下图所示的表就不符合 1NF 的要求:![](/media/202107/2021-07-02_162437.png) 2. 为了满足 1NF 的要求,上面的表应该改为下图的形式:![](/media/202107/2021-07-02_162509.png) ### 1.3 存在的问题 如果仅仅符合 1NF 的设计,仍然会存在**数据冗余过大**、**插入异常**、**删除异常**、**修改异常**的问题,例如对于下图中表的设计: ![](/media/202107/2021-07-02_162829.png) 1. **数据冗余过大:** 1. 每一名学生的学号、姓名、系名、系主任这些数据重复多次。 2. 每个系与对应的系主任的数据也重复多次。 2. **插入异常:** 1. 假如学校新建了一个系,但是暂时还没有招收任何学生(比如 3 月份就新建了,但要等到 8 月份才招生),那么是无法将系名与系主任的数据单独地添加到数据表中去的。 3. **删除异常:** 1. 假如将某个系中所有学生相关的记录都删除,那么所有系与系主任的数据也就随之消失了(一个系所有学生都没有了,并不表示这个系就没有了)。 4. **修改异常:** 1. 假如李小明转系到法律系,那么为了保证数据库中数据的一致性,需要修改三条记录中系与系主任的数据。 ## 2 第二范式(2NF) > 正因为仅符合 1NF 的数据库设计存在着上面提到的那些问题,我们需要提高设计标准,去掉导致上述四种问题的因素,使其符合更高一级的范式(2NF),这就是所谓的“规范化”。 ### 2.1 相关概念 #### 2.1.1 函数依赖 ##### 2.1.1.1 含义 1. 若在一张表中,**在属性或属性组 $X$ 的值确定的情况下**,**必定能确定属性 $Y$ 的值**,那么就可以说 $Y$**函数依赖于**$X$,写作 $X \rightarrow Y$。 2. 也就是说,在数据表中,**不存在任意两条记录**,他们**在 $X$ 上的值相同**,而**在 $Y$ 属性上的值不同**。 3. 类似于**函数关系**$y = f(x)$,在 $x$**的值确定的情况下**,$y$**的值一定是确定的**。 ##### 2.1.1.2 示例 1. 例如,在上面的图中,找不到任何一条记录,他们的学号相同,而对应的姓名不同,所以我们可以说**姓名函数依赖于学号**,写作 $ 学号 \rightarrow 姓名 $,但是反过来,因为可能出现同名的学生,所以有可能不同的两条学生记录,他们在姓名上的值相同,但对应的学号不同,所以我们**不能说学号依赖于姓名**。 2. 上图中存在的其它函数依赖关系如下: 1. $ 系名 \rightarrow 系主任 $。 2. $ 学号 \rightarrow 系主任 $。 3. $(学号,课名) \rightarrow 分数 $。 3. 但如下依赖关系则不成立: 1. $ 学号 \rightarrow 课名 $。 2. $ 学号 \rightarrow 分数 $。 3. $ 课名 \rightarrow 系主任 $。 4. $(学号,课名) \rightarrow 姓名 $。 ##### 2.1.1.3 相关概念 ###### 2.1.1.3.1 完全函数依赖 1. 在一张表中,若 $X \rightarrow Y$,且对于 $X$ 的**任意一个真子集 $X^{'}$**(假如属性组 $X$ 包含超过一个属性),$X^{'} \rightarrow Y$**不成立**,那么我们称 $Y$**完全函数依赖于**$X$,记作 $X \xrightarrow F Y$。 2. 例如: 1. $ 学号 \xrightarrow F 姓名 $。 2. $(学号,课名) \xrightarrow F 分数 $。 ###### 2.1.1.3.2 部分函数依赖 1. 在一张表中,若 $X \rightarrow Y$,且 $Y$**不完全函数依赖于 $X$**,那么我们就称 $Y$**部分函数依赖于 $X$**,记作 $X \xrightarrow P Y$。 2. 例如: 1. $(学号,课名) \xrightarrow P 姓名 $。 ###### 2.1.1.3.3 传递函数依赖 1. 假如 $Z \rightarrow Y$,且 $Y \rightarrow X$($X \notin Y$,且 $X$ 不函数依赖于 $Y$),那么我们就称 $Z$**传递函数依赖于**$X$,记作 $X \xrightarrow T Z$。 #### 2.1.2 码 ##### 2.1.2.1 含义 1. 设 $K$ 为某表中的一个属性或属性组,若**除 $K$ 之外的所有属性都完全函数依赖于 $K$**,那么我们称 $K$ 为**候选码**,简称为**码**。 2. 在实际中我们通常可以理解为**假如当 $K$ 确定之后**,**该表除 $K$ 外的所有属性的值也就随之确定**,**那么 $K$ 就是码**。 3. 一张表中可以有超过一个码,实际应用中为了方便,通常**选择其中的一个作为主码**。 ##### 2.1.2.2 示例 1. $(学号,课名)$ 这个属性组就是码,该表中有且仅有这一个码。 #### 2.1.3 主属性 ##### 2.1.3.1 含义 1. **包含在任何一个码中的属性称为主属性**。 ##### 2.1.3.2 示例 1. 对于上图中,主属性就有两个,分别是**学号**和**课名**。 ### 2.2 含义 1. 2NF 在 1NF 的基础上,**消除了非主属性对于码的部分依赖**(属性完全依赖于主键)。 2. 判断一张表是否符合2NF的方法: 1. 第一步:**找出数据表中所有的码**。 2. 第二步:**根据**第一步得到的**码**,**找出所有的主属性**。 3. 第三步:数据表中,除去所有的主属性,剩下的就都是**非主属性**了。 4. 第四步:查看**是否存在非主属性对码的部分依赖**。 ### 2.3 示例 1. 第一步:下图中表示了上面的**表中所有的函数依赖关系**,这一步完成后,可以得到,上面的表的**码只有一个**,**就是$(学号,课名)$**。 ![](/media/202107/2021-07-03_143357.png) 2. 第二步:**主属性有两个**,分别为**学号**和**课名**。 3. 第三步:**非主属性有四个**,分别为**姓名**、**系名**、**系主任**、**分数**。 4. 第四步: 1. 对于$(学号,课名) \rightarrow 姓名$,有$学号 \rightarrow 姓名$,**存在非主属性姓名对码$(学号,课名)$的部分函数依赖**。 2. 对于$(学号,课名) \rightarrow 系名$,有$学号 \rightarrow 系名$,**存在非主属性系名对码$(学号,课名)$的部分函数依赖**。 3. 对于$(学号,课名) \rightarrow 系主任$,有$学号 \rightarrow 系主任$,**存在非主属性对码$(学号,课名)$的部分函数依赖**。 所以上面的表**存在非主属性对于码的部分函数依赖**,**最高只符合1NF的要求**,**不符合2NF的要求**。 ### 2.4 如何使1NF的表符合2NF 1. 为了让上面的表符合2NF的要求,我们必须**消除这些部分函数的依赖**,只有一个办法,就是**将大数据表拆分成两个或者更多个更小的数据表**,在拆分的过程中,要达到更高一级范式的要求,这个过程叫做**模式分解**,**模式分解的方法不是唯一的**,以下是其中一种方法: 1. **选课**(学号、课名、分数)。 2. **学生**(学号、姓名、系名、系主任)。 2. 我们先来判断一下选课表与学生表是否符合了2NF的要求: 1. 对于**选课表**,其**码是**$(学号,课名)$,**主属性是学号**、**课名**,**非主属性是分数**,**只有学号和课名都确定的情况下**,**才能唯一确定分数**,因此**不存在非主属性对于码的部分函数依赖**,**符合2NF的要求**。 2. 对于**学生表**,其**码是**$(学号)$,**主属性是学号**,**非主属性是姓名**、**系名**、**系主任**,因为**码只有一个**,所以**不可能存在非主属性对于码的部分函数依赖**,因此**此表符合2NF的要求**。 3. 下图展示了模式分解以后的新的函数依赖关系:![](https://pic1.zhimg.com/80/2f4b4a887f6a61674a49d03d79e3fe17_1440w.jpg?source=1940ef5c) 4. 下图展示了模式分解以后新的数据:![](https://pic1.zhimg.com/80/44af74509a4e21372ed372be8560539d_1440w.jpg?source=1940ef5c) ### 2.5 1NF问题解决状态 #### 2.5.1 已解决 1. **数据冗余过大:** 1. 学生的姓名、系名与系主任,**不再像之前一样重复多次了**。 2. **修改异常:** 1. 李小明**转到法律系后只需要修改一次对应的系的值**即可。 #### 2.5.2 未解决 1. **插入异常:** 1. 当**插入一个尚无学生的新系的新系时**,因为**学生表的码是学号**,**不能为空**,所以**此操作不被允许**。 2. **删除异常:** 1. 当**删除某个系中所有的学生记录时**,**该系的信息会全部丢失**。 ## 3 第三范式(3NF) ### 3.1 含义 1. 3NF在2NF的基础上,**消除了非主属性对于码的传递函数依赖**。 2. 符合3NF要求的数据库设计,**基本上解决了数据冗余过大**、**插入异常**、**修改异常**、**删除异常的问题**。 ### 3.2 示例 我们先看一下上面符合2NF表的设计是否符合3NF的要求: 1. 对于**选课表**,**主码为**$(学号,课名)$,**主属性为学号和课名**,**非主属性只有一个**,**为分数**,**不可能存在传递函数依赖**,所以**选课表的设计符合3NF的要求**。 2. 对于**学生表**,**主码为**$学号$,**主属性为学号**,**非主属性为姓名**、**系名**、**系主任**,因为$姓名 \rightarrow 系名$,$系名 \rightarrow 系主任$,所以**存在非主属性系主任对于码学号的传递函数依赖**,所以**学生表的设计不符合3NF的要求**。 ### 3.3 如何使2NF的表符合3NF 1. 为了让数据表设计达到3NF,我们必须进一步进行模式分解为以下形式: 1. **选课**(学号、课名、分数)。 2. **学生**(学号、姓名、系名)。 3. **系**(系名、系主任)。 2. 下面我们看一下分解后的表是否符合3NF: 1. 对于**选课表**,**符合3NF的要求,这个我们上面已经分析过了**。 2. 对于**学生表**,**码为学号**,**主属性为学号**,**非主属性为系名**,**不可能存在非主属性对于码的传递函数依赖**。 3. 对于**系表**,**码为系名**,**主属性为系名**,**非主属性为系主任**,**不可能存在非主属性对于码的传递函数依赖**(**至少要有三个属性才可能存在传递函数依赖关系**),所以**符合3NF的要求**。 3. 新的函数依赖关系如下图所示:![](https://pic4.zhimg.com/80/5b20707ff3d9afb51ef7bfda726c3e34_1440w.jpg?source=1940ef5c) 4. 新的数据表如下图所示:![](https://pic1.zhimg.com/80/8bca802bcff92a8945bf808d18d7ec62_1440w.jpg?source=1940ef5c) ### 3.4 2NF问题解决状态 #### 3.4.1 已解决 1. **插入异常:** 1. 当**插入一个尚无学生的新系的信息**时,由于**系表与学生表目前是独立的两张表**,所以**不影响**。 2. **删除异常:** 1. 当**删除某个系中所有的学生记录**时,**该系的信息不会丢失**。 ## 参考文献 1. [如何理解关系型数据库的常见设计范式?](https://www.zhihu.com/question/24696366/answer/29189700)
ricear
2021年7月3日 15:51
©
BY-NC-ND(4.0)
转发文档
收藏文档
上一篇
下一篇
手机扫码
复制链接
手机扫一扫转发分享
复制链接
Markdown文件
分享
链接
类型
密码
更新密码