基本概念
- 数据库是长期存储在计算机内、有组织的、可共享的大量数据的集合
- 关系模式:描述关系数据库中表的结构和约束的抽象。它定义了表的名字、表中列(属性)的名字和数据类型,以及表中列之间的约束(如主键、外键、唯一性等)。关系模式本身并不存储数据,而是定义了数据的布局和结构。
- 表(Table):是数据库中实际存储数据的结构。每一个关系模式对应数据库中的一个表。表由数据行(tuple)和列(column)组成,数据行表示实体(如一个学生、一个课程),而列表示属性(如学生的ID、姓名等)。
三级模式(Three-Level Schema)
数据库三级模式(Three-Level Schema)是指数据库中数据的抽象层次结构,定义了不同的模式(Schema)层次以及它们之间的映射关系。其关键目的是通过层次化设计实现数据的独立性,简化数据库的管理与应用开发。在此架构中,两层映射关系指的是不同层次之间如何互相转换、传递数据,并保证数据的一致性和透明性。
三层模式体系结构
内部模式(Internal Schema)
- 也称为物理模式(Physical Schema),它描述了数据的实际存储方式及访问路径。
- 该层定义了数据库在存储介质上的物理存储方式、数据的存储结构(如索引、文件、记录格式等)。
- 主要涉及如何在磁盘上高效地存储数据以及如何通过存储结构(如页、块、树形结构等)加速查询操作。
- 内部模式决定了数据库的存储效率与性能。
概念模式(Conceptual Schema)
- 也称为逻辑模式(Logical Schema),它描述了数据库中所有数据的逻辑结构和关系。
- 该层提供了数据库的整体视图,不涉及具体的存储细节,定义了表、字段、记录、数据类型、约束等。
- 概念模式是对数据库中数据的抽象化描述,独立于数据的物理存储方式。
- 该层关注数据的整体结构和数据库的业务逻辑,解决了数据与应用程序的逻辑问题。
外部模式(External Schema)
- 也称为视图模式(View Schema),它是数据库的用户视图层,定义了用户或应用程序与数据库的交互方式。
- 该层定义了不同用户或者不同应用程序可以访问的数据视图,用户可以只访问数据库中的一部分数据(例如某个表的子集、某些字段、某些条件下的记录等)。
- 外部模式帮助实现数据的安全性和权限控制,不同用户可以对数据库进行不同的操作,而不必了解数据的具体存储和整体结构。
- 一个数据库系统可以有多个外部模式,每个外部模式代表不同的用户需求或应用场景。
两层映射关系
在三级模式结构中,映射关系是:
外部模式与概念模式之间的映射
- 体现数据的逻辑独立性
- 该映射定义了如何将概念模式中的数据表、字段等抽象结构映射到用户所看到的具体数据视图中。
- 外部模式与概念模式的映射通常是一个逻辑映射,外部模式通常不包含概念模式中所有的表,它们只会展现用户需要看到的数据部分。不同用户和应用可能有不同的外部视图。
概念模式与内部模式之间的映射
- 体现数据的物理独立性
- 该映射描述了数据如何从物理存储(即内部模式)映射到概念模式中。这通常涉及如何将表、索引、视图等数据结构从物理存储抽象到逻辑数据结构。
- 例如,概念模式中的一个表可能由多个磁盘块或文件组成,概念模式与内部模式之间的映射确保了查询操作在不暴露存储细节的情况下仍能高效执行。
三层模式特点
- 数据独立性:三层模式的最大优势是提供了数据的独立性。通过将物理层(内部模式)与逻辑层(概念模式)以及外部层(外部模式)分离,可以实现数据的物理独立性(内部模式变化不影响概念模式)和逻辑独立性(概念模式变化不影响外部模式)。这意味着数据库的结构和存储方式可以发生变化而不影响应用程序和用户。
- 增强的灵活性:每一层的变化都不会直接影响其他层,使得数据库系统在面对需求变化、硬件更新等情况时更加灵活。
- 简化数据管理:不同的用户可以根据其权限访问不同的数据视图,无需关心数据的底层存储方式,简化了数据管理和操作。
- 安全性和访问控制:通过外部模式的不同定义,可以针对不同的用户或应用程序限制访问特定的数据,增强了数据库的安全性。
关系表类型
- 基本关系(基本表、基表):实际存在的表,实际存储数据的逻辑表示
- 查询表:查询表并不是一个物理表,而是通过特定的查询操作(如SELECT)在基础表上动态生成的结果集。这些查询表通常不保存数据,而是每次执行查询时计算出当前的数据
- 视图表:由基表或其他视图表导出的表,本身不独立存储,数据库只存放它的定义,常称为虚表
数据库视图(View)
数据库视图是一个虚拟的表,它是通过一个或多个数据库表的查询结果定义的。视图本身并不存储数据,而是通过查询语句动态地从基础表中获取数据。视图用于简化复杂查询、增强数据安全性以及支持逻辑抽象。
视图的特点
- 虚拟表:视图是一个虚拟的表,数据并不存储在视图本身中,而是基于查询时从基础表中动态生成的。
- 简化查询:视图可以将复杂的查询封装成简单的查询接口,使用户和应用程序能够更加方便地访问数据。
- 提高数据安全性:视图可以限制用户访问表中的敏感数据,通过只展示必要的数据列和行来保护底层数据。
- 支持逻辑抽象:通过视图,用户可以将多个表的数据结合在一起,进行更高层次的数据抽象,从而提高应用的灵活性。
- 更新限制:某些情况下,视图的内容是不可更新的,尤其是当视图涉及多个表的连接、聚合函数或分组时。并不是所有视图都支持更新操作。
视图的优缺点
优点:
- 简化查询:视图能够封装复杂的查询逻辑,使得用户可以以更简洁的方式获取结果。
- 数据安全性:通过视图可以限制对敏感数据的访问,仅提供必要的列和行。
- 一致性:视图能够提供一致的查询接口,特别是在底层表结构发生变化时,只要视图定义不变,应用程序的查询代码也无需修改(逻辑独立性)。
- 抽象性:通过视图,可以将底层数据模型抽象出来,简化对数据库的操作。
缺点:
- 性能开销:每次访问视图时,底层的查询会重新执行,可能会影响性能。尤其对于复杂视图,性能可能较差。
- 更新限制:对于涉及多个表的视图,通常不支持直接更新操作,限制了其灵活性。
- 维护复杂性:如果视图的定义非常复杂或涉及多个表,在表结构变化时需要小心维护视图的有效性。
物化视图(Materialized View)
- 与普通视图不同,物化视图会将查询结果存储在物理存储中,并定期更新。这能够显著提高查询效率,特别是对于计算开销较大的查询。
- 支持手动或定期刷新数据。
- 适用于需要频繁访问大数据量的应用场景,减少了实时计算的成本(少更新)。
集中式数据库
分布式数据库
分布式数据库是将数据存储在多个物理位置的数据库管理系统(DBMS),这些数据可以分布在不同的计算机或地理位置。它通常由多个节点组成,每个节点可以是一个物理服务器或者一个虚拟实例,彼此通过网络连接。
特点
- 数据独立性:除了数据的逻辑独立性和物理独立性之外,还有数据分布独立性(分布透明性)
- 集中与自治共享结合的控制结构:各局部的 DBMS 可以独立地管理局部数据库,具有自治功能,同时系统又设有集中控制机制,协调各局部 DBMS 的工作,执行全局应用
- 适当增加数据冗余度:在不同的场地存储同一数据的多个副本,可以提高系统的可靠性和可用性,同时也能提高系统性能。(提高系统的可用性,即当系统中某个节点发生故障时,因为数据有其他副本在非故障场地上,对其他所有场所来说,数据仍然是可用的,从而保证数据的完备性)
- 全局的一致性、可串行性和可恢复性
结构
全局概念模式(Global Conceptual Schema)
全局概念模式是一个逻辑层,它定义了整个分布式数据库系统中所有数据的整体结构和关系。它描述了数据库中所有的数据元素及其相互关系,是所有局部模式(local schemas)的集成,并不关心数据的物理存储方式或分布位置。全局概念模式提供的是数据的统一逻辑视图。
全局外模式(Global External Schema)
全局外模式是用户视图层,它为不同的用户或应用程序提供了定制化的数据视图。全局外模式定义了特定用户或应用程序如何访问和操作全局概念模式中定义的数据,但不会影响全局概念模式本身。
管理系统组成
- 局部数据库管理系统(LDBMS)
- 全局数据库管理系统(GDBMS)
- 全局通信字典
- 通信管理(CM)
管理系统结构
- 全局控制集中的分布式数据库管理系统(DDBMS)
- 全局控制分散的分布式数据库管理系统(DDBMS)
- 全局控制部分分散的分布式数据库管理系统(DDBMS)
数据分片(Data Sharding)
将数据划分成多个独立的部分,每个部分称为“分片” (Shard),并将这些分片分布在多个数据库节点上进行存储。通过这种方式,可以提高数据库系统的可扩展性、性能和可用性,减少单个节点的负载,从而支持更高的并发和大规模的数据处理。
类型
分片类型 | 说明 | 优势 | 挑战 | 适用场景 |
---|---|---|---|---|
水平分片 | 按行划分数据 | 高可扩展性,分布均匀 | 复杂查询,数据倾斜 | 数据量大,增长快速的应用 |
垂直分片 | 按列划分数据 | 提高查询效率,数据访问优化 | 需要精确控制每列的访问频率 | 各列数据访问频率差异较大的表 |
哈希分片 | 按哈希值划分数据 | 数据分布均匀,负载均衡 | 查询复杂性较高,跨分片查询 | 高并发,数据量大,查询负载均匀 |
范围分片 | 按数据范围划分 | 简单直观,适用于范围查询 | 数据倾斜,查询可能不均匀 | 范围查询为主,数据分布较均匀 |
水平分片(Horizontal Sharding)
将数据表中的行(记录)划分成多个部分,每一部分存储在不同的服务器上。每个分片存储表中的一部分数据,通常基于某个字段(例如,ID、地区等)来决定哪些数据存储在哪个分片上。
垂直分片(Vertical Sharding)
将数据表中的列划分成多个部分,存储在不同的分片中。每个分片存储表的不同列。
哈希分片(Hash Sharding)
根据哈希函数将数据分布到不同的分片上。哈希函数根据某个字段的值(通常是主键)计算一个哈希值,然后将数据根据该哈希值存储到不同的分片中。
范围分片(Range Sharding)
将数据根据某个字段的值的范围划分为多个分片。例如,将用户数据按用户ID、创建时间等字段的范围划分成不同的分片。
混合分片(Hybrid Sharding)
混合分片策略是指在一个系统中同时采用多种分片策略,将其优点结合使用,以应对不同的数据分布和访问模式。
分片类型 | 组合方式 | 优势 | 挑战 | 适用场景 |
---|---|---|---|---|
水平分片 + 范围分片 | 先按某字段进行水平分片,再在每个分片中进行范围分片 | 支持高效的范围查询,数据均匀分布 | 跨范围查询的复杂性,可能出现数据倾斜问题 | 时间序列数据、按日期分布的数据 |
水平分片 + 哈希分片 | 先按某字段进行水平分片,再在每个分片内进行哈希分片 | 负载均衡,数据均匀分布 | 跨分片查询复杂性,增加了哈希计算开销 | 大规模并发查询,负载均衡要求较高的场景 |
垂直分片 + 水平分片 | 先按列进行垂直分片,再按行进行水平分片 | 列访问优化,行数据扩展性高 | 列和行的分配需要精细控制 | 列访问频率差异较大的应用,如电商商品表 |
范围分片 + 哈希分片 | 先按范围进行分片,再在每个范围内进行哈希分片 | 高效范围查询和负载均衡 | 需要解决跨分片查询的性能瓶颈 | 大数据量的范围查询,数据分布不均匀的情况 |
分布透明性
- 分片透明性:用户不必关心数据是如何分片的,它们对数据的操作在全局关系上进行,即如何分片对用户是透明的
- 复制透明性:用户不需要了解数据库中数据的复制情况。系统自动管理数据的复制和同步
- 位置透明性:用户不需要知道数据存储在哪个具体的物理位置。数据库系统通过内部机制来定位和访问数据
- 逻辑透明性(局部数据模型透明性):提供数据到局部数据库的映像,即用户不必关心局部 DBMS 支持哪种数据模型、使用哪种数据操纵语言,数据模型和操纵语言的转换是由系统完成的。因此,局部映像透明性对异构型和同构异质的分布式数据库系统是非常重要的
两阶段提交协议(2PC,Two-Phase Commit Protocol)
一种常用于分布式数据库中的协议,确保在分布式系统中,事务的原子性得到保证。它的主要目的是确保所有参与者(节点)在分布式事务中要么全部提交,要么全部回滚,避免部分成功、部分失败的情况。
第一阶段:表决阶段(Voting Phase)
- 事务协调者(通常是发起事务的节点)向所有参与者(即涉及的数据库节点)发送一个请求,询问它们是否可以准备提交事务。
- 每个参与者节点会根据自己的状态做出响应:
- 如果可以提交事务,参与者节点会准备好提交,发送一个“准备提交”信号(
Vote: Yes
)。 - 如果参与者节点遇到任何问题,无法提交事务,它会发送一个“拒绝”信号(
Vote: No
)。
- 如果可以提交事务,参与者节点会准备好提交,发送一个“准备提交”信号(
第二阶段:执行阶段(Execution Phase)
-
协调者收到所有参与者的响应后:
- 如果所有参与者都返回“准备提交”,协调者会发出“提交”信号,指示所有节点提交事务。
- 如果有任何参与者返回“拒绝”,协调者会发出“回滚”信号,指示所有节点回滚事务。
关键点
- 原子性:两阶段提交确保了事务要么完全提交,要么完全回滚,防止部分节点提交、部分节点回滚的情况。
- 一致性:所有节点在同一时间提交或回滚,保持系统的一致性。
- 阻塞问题:在某些情况下,若协调者崩溃或者无法联系到某些参与者,可能导致系统阻塞(特别是当某个节点等待协调者的指令时)。
数据模型
数据模型定义了数据库中数据的结构、关系、约束以及操作方式。数据模型的选择直接影响数据库的设计、性能、可维护性和扩展性。
数据模型的三要素
任何类型的数据模型都包含以下三要素:
数据结构(Data Structure):定义数据如何组织和存储。关系模型中的数据结构是表,层次模型中的数据结构是树,而面向对象模型中的数据结构是对象。
数据操作(Data Operations):定义对数据的操作方式,包括查询、插入、删除、更新等操作。关系模型中通过SQL语言进行操作,文档模型和键值模型通常使用API进行操作。
数据约束(Data Constraints):定义数据的合法性和完整性规则,确保数据在存储和操作时满足一定的规范。例如,关系模型中有主键约束、外键约束和非空约束等。
数据模型的主要类型
数据模型类型 | 描述 | 特点 | 应用 |
---|---|---|---|
关系模型 | 关系模型通过表(关系)来组织数据,数据之间通过主键和外键的关系来实现关联。每个表由行(元组)和列(属性)组成。关系模型是目前最常用的数据模型,广泛应用于关系型数据库管理系统(RDBMS)中。 | - 数据存储在表中,行表示记录,列表示属性。 - 使用关系操作(如选择、投影、连接等)来查询和操作数据 - 强调数据的结构化和规范化,以减少冗余数据,确保数据一致性。 |
SQL(Structured Query Language)是关系模型的查询语言,广泛应用于MySQL、Oracle、PostgreSQL等数据库系统。 |
层次模型(Hierarchical Model) | 层次模型采用树状结构来表示数据,数据以层次化的方式组织成父子关系。每个父节点可以有多个子节点,但每个子节点只能有一个父节点。它适用于表示具有自然层次结构的数据,如组织结构图、文件系统等。 | - 数据呈现为父子节点的结构,类似于树形图。 - 支持快速的导航和查询,尤其在读取操作上效率较高。 - 在层次模型中,父节点和子节点之间的关系是固定的,不能灵活处理多对多关系。 |
层次模型主要用于早期的数据库管理系统,如IBM的IMS。 |
网状模型(Network Model) | 网状模型是层次模型的扩展,允许数据元素之间存在多对多的关系。数据元素通过指针(或链接)互相连接,形成一个复杂的网状结构。 | - 支持多对多的关系,通过指针连接不同的记录。 - 灵活性较高,但比层次模型复杂,查询的复杂度较高。 - 数据的插入和删除操作较为复杂。 |
网状模型的代表是CODASYL DBMS,如早期的IDMS(Integrated Database Management System)。 |
面向对象模型(Object-Oriented Model) | 面向对象模型采用面向对象的思想来组织数据,将数据表示为对象(Object),对象由属性和方法组成。对象之间可以通过继承、封装和多态等面向对象的概念来建立关系。 | - 数据和操作(方法)被封装在一起,支持更复杂的数据类型,如图像、音频等。 - 支持继承、多态、封装等面向对象的特性,可以更好地模拟现实世界的复杂关系。 - 适合处理复杂的数据和应用场景,但对于传统的关系数据处理支持较弱。 |
面向对象数据库(如ObjectDB、db4o)和一些面向对象的关系数据库(如PostgreSQL的对象关系扩展)。 |
关系模型(Relational Model)
基本概念
1. 关系(Relation)
关系是数据库中用于表示数据的一种结构,它由一组行和列组成。每个关系可以看作是一张表,表中的每一行表示一个实体或记录,而每一列表示该实体的一个属性。
-
特点:
- 每个关系(表)有一个唯一的名字。
- 每个关系由多个属性组成,属性对应表中的列。
- 每个关系中的每一行(元组)是唯一的,不能重复。
2. 元组(Tuple)
元组是关系中的一行,也就是表中的一条记录。每个元组包含一组属性值,这些属性值对应于关系的不同列。
-
特点:
- 每个元组的属性值都来自于相应属性的域。
- 每个元组在表中是唯一的。
3. 属性(Attribute)
属性是关系中的列,表示某一类信息的特征或属性。每个属性都有一个名称和一个数据类型,定义了该列存储的数据的格式。
-
特点:
- 每个属性对应一个数据类型(例如:整数、字符、日期等)。
- 属性的名称应具有唯一性。
-
例子:在学生表中,
学生ID
、姓名
、年龄
都是属性。
4. 域(Domain)
域是属性可能取的所有值的集合。每个属性都有一个对应的域,它定义了该属性值的取值范围、数据类型及可能的约束。
-
特点:
- 域约束确保了每个属性值的合法性。
- 域可以是原子值集合(例如整数、字符串)或更复杂的值集合。
-
例子:
-
学生ID
的域可能是所有正整数。 -
姓名
的域是所有字符串。 -
年龄
的域是所有非负整数。
-
5. 候选键(Candidate Key,候选码)
候选键是关系中能够唯一标识每一行的属性或属性组合。每个关系可以有多个候选键,但必须选择一个作为主键。
-
特点:
- 每个候选键都可以唯一标识元组。
- 候选键的最小性:候选键的属性不能去掉任何一个,否则就不再能唯一标识元组。(无冗余)
-
例子:在学生表中,
学生ID
是一个候选键,姓名 + 年龄
也可能是一个候选键(假设没有两个年龄相同、姓名相同的学生)。但最终,我们选择学生ID
作为主键。
6. 主键(Primary Key)
主键是一个或多个属性的组合,用于唯一标识关系中的每一行(元组)。主键的值必须唯一且不能为NULL。
-
特点:
- 每个关系只能有一个主键。
- 主键的值必须唯一,不能重复。
- 主键用于快速定位元组。
-
例子:在学生表中,
学生ID
是主键,因为每个学生ID都是唯一的。
7. 外键(Foreign Key)
外键是一个或多个属性,用于在一个关系中引用另一个关系的主键。外键用于建立表之间的关联,保证数据的参照完整性。
-
特点:
- 外键指向另一个关系的主键或候选键。
- 外键的值可以为NULL,或者它的值必须存在于目标表的主键中。
-
例子:假设有一个"课程"表和一个"选课"表,"选课"表中的
学生ID
是外键,指向"学生"表中的学生ID
主键。
8. 度(Degree)
关系的度是关系中属性的数量,即表中的列数。
- 作用:度反映了关系的结构复杂度,关系的度越高,表的列数就越多。每个属性表示数据的一种特征。
9. 目(Cardinality)
关系的目是关系中元组的数量,即表中的行数。
- 作用:目反映了关系中记录的数量。目越大,意味着该表存储了更多的数据。
10. 关系的基数(Cardinality)
基数表示一个关系中某一属性可能的取值个数。它通常用来描述关系中的元组数目。
-
特点:
- 基数与关系中实际存储的数据量有关。
-
例子:
- 如果学生表中有1000条记录,那么基数为1000。
关系操作(Relational Operations)
关系模型通过一系列的操作来对数据进行查询和更新,这些操作通常基于集合理论,主要包括以下几种:
- 选择(Selection, σ):选择满足条件的元组。
- 投影(Projection, π):从关系中选择某些特定的列。
- 连接(Join):将两个关系按照某些公共属性连接起来。
- 并集(Union):将两个关系的元组合并(要求关系结构相同)。
- 差集(Difference):返回在第一个关系中存在而第二个关系中不存在的元组。
- 笛卡尔积(Cartesian Product):返回两个关系的所有可能元组组合。
- 交集(Intersection):返回两个关系中相同的元组。
完整性约束(Integrity Constraints)
完整性约束确保数据的正确性和一致性。主要包括以下几类:
- 实体完整性(Entity Integrity):确保主键值不为空,保证每个元组唯一。
- 参照完整性(Referential Integrity):确保外键所引用的数据必须在目标关系中存在。
- 域完整性(Domain Integrity):确保每个属性值都来自其定义的域。
- 用户定义的完整性(User-Defined Integrity):基于应用的特殊约束,如数据值范围限制等。
关系代数(Relational Algebra)
关系数据库理论中用于操作关系(即表)的理论基础,它提供了一组数学运算符,用于在数据库中查询和操作数据。关系代数的主要作用是定义数据库查询的操作模型,它是关系数据库管理系统(RDBMS)执行查询和优化的基础。关系代数的主要操作是基于
集合论的操作,如选择、投影等。所有的操作结果都会返回一个新的关系(表),关系代数的操作具有封闭性
。它的主要优点是能够以一种清晰、形式化的方式定义查询和更新数据的方式。
基本操作
关系代数包括一些常见的基本操作符,每个操作符都可以应用于一个或多个关系,生成新的关系。下面是主要的关系代数操作:
1. 选择(Selection, σ)
选择操作从关系中选出满足特定条件的元组(行)。它相当于 SQL 中的 WHERE
子句。
语法:
σ_条件(关系)
-
示例:从学生表中选出年龄大于 20 的学生
σ_年龄 > 20(学生表)
2. 投影(Projection, π)
投影操作从关系中选出特定的列(属性),去除其他不需要的列,相当于 SQL 中的 SELECT
子句。
语法:
π_列名(关系)
-
示例:从学生表中选出学生ID和姓名
π_学生ID, 姓名(学生表)
3. 并(Union, ∪)
并操作将两个关系中的元组合并,去除重复项,要求两个关系具有相同的属性(同名且类型相同)。
语法:
关系1 ∪ 关系2
-
示例:选择所有在两个课程表中的学生
学生表1 ∪ 学生表2
4. 差(Difference, -)
差操作返回在第一个关系中但不在第二个关系中的元组,相当于 SQL 中的 EXCEPT
子句。
语法:
关系1 - 关系2
-
示例:从学生表中选出不选修某门课程的学生
学生表 - 选修课程表
5. 笛卡尔积(Cartesian Product, ×)
笛卡尔积操作返回两个关系的所有元组的组合,生成一个包含所有属性的关系。结果是两个关系的所有元组的组合。
语法:
关系1 × 关系2
-
示例:学生表和课程表的笛卡尔积
学生表 × 课程表
复合操作
1. 交(Intersection, ∩)
交操作用于返回两个关系中共同存在的元组,类似于集合论中的交集操作。即,交操作返回的是同时出现在两个关系中的元组。要求两个关系有相同的属性(列)。
- 语法:关系1 ∩ 关系2
- 描述:返回关系1和关系2中的交集(即两个关系中都有的元组)。
- 条件:交操作要求参与操作的两个关系有相同的结构(即具有相同的列),否则无法进行交集操作。
- 基于基本操作:
2. 连接(Join, ⨝)
连接操作将两个关系根据某些条件连接起来,常用于关联查询。最常见的连接是等值连接(Equi Join)和自然连接(Natural Join)。
语法:
关系1 ⨝_条件 关系2
基于基本操作:
-
示例:通过学生ID连接学生表和选课表
学生表 ⨝ 学生ID=学生ID 选课表
3. 除法(Division, ÷)
除法操作用于查询那些与另一个关系的所有元组都相关联的元组。它常常用于“满足所有条件”的查询。
语法:
关系1 ÷ 关系2
基于基本操作:
-
示例:查询选修了所有课程的学生
选修学生表 ÷ 所有课程表
规范化理论(Normalization Theory)
一个用于设计关系型数据库结构的理论,它通过一系列的规则和步骤将数据从冗余、不一致、难以维护的设计转化为简洁、高效且一致的数据结构。规范化的核心目标是消除数据冗余、避免更新异常和插入异常,并确保数据的完整性。
规范化的目的
规范化的主要目的是通过将数据表的结构优化,达到以下目标:
- 消除数据冗余:减少重复存储的数据,节省存储空间。
- 避免更新异常:避免在插入、更新或删除操作时产生不一致或错误的数据。
- 提高数据一致性:确保数据在整个数据库中是一致的,避免因冗余或依赖问题导致的错误。
- 增强数据完整性:确保数据符合业务规则和逻辑关系,保持数据的正确性和一致性。
函数依赖(Functional Dependency, FD)
描述一个数据表中某些属性如何依赖于其他属性的规则。具体来说,在一个关系(即数据表)中,如果某个属性集(或属性组合)决定了另一个属性的值,那么我们称这个关系存在
函数依赖。如果在一个关系中,属性集X 决定了属性 Y 的值,记作:
X → Y
函数依赖的类型:
-
完全函数依赖(Full Functional Dependency):如果属性
Y
完全依赖于属性集X
,即没有任何冗余属性集能决定Y
,则称Y
完全依赖于X
。 -
部分函数依赖(Partial Functional Dependency):如果属性
Y
依赖于属性集X
的某一部分,而不是整个X
,则称Y
部分依赖于X
。 -
传递函数依赖(Transitive Dependency):如果属性
X
决定了属性Y
,而属性Y
又决定了属性Z
,则称Z
通过Y
间接依赖于X
,这是传递依赖。 -
自反函数依赖(Trivial Functional Dependency):对于任何属性集
X
,都有X → X
,即任何属性集总是自我决定的,这被称为自反依赖。 - 多值依赖(Multivalued Dependency):这是一个更复杂的依赖类型,表示一个属性集决定了多个属性集的值。
图示法求取候选键
- 将关系模式的函数依赖关系用有向图的方式表示
- 找入度为0的属性,并以该属性集合为起点,尝试遍历有向图,若能正常遍历图中所有节点,则该属性集记为关系模式的候选键
- 若入度为0的属性集不能遍历图中所有节点,则需要尝试性的将一些中间节点(既有入度,也有出度的节点)并入入度为0的属性集中,直至该集合能遍历所有节点,集合为候选键
公式法
Armstrong 公理(Armstrong's Axioms)
一组用于推导函数依赖(Functional Dependency, FD)关系的基本规则。在数据库设计中,函数依赖是描述一个属性集如何决定其他属性集的关系,而 Armstrong 公理为推导和验证这些函数依赖提供了一组完备的推导规则。
Armstrong 公理的三条基本公理
-
自反性(Reflexivity):大决定小
- 如果
Y
是X
的子集,那么X → Y
是一个有效的函数依赖。 - 形式化:如果
Y ⊆ X
,则X → Y
。 - 例子:如果
A, B → A
,因为A
是A, B
的子集。
- 如果
-
增广性(Augmentation):
- 如果
X → Y
是一个有效的函数依赖,并且Z
是任意的属性集,那么X, Z → Y, Z
也是一个有效的函数依赖。 - 形式化:如果
X → Y
,那么X, Z → Y, Z
。 - 例子:如果
A → B
,那么A, C → B, C
也是有效的函数依赖。
- 如果
-
传递性(Transitivity):
- 如果
X → Y
和Y → Z
是有效的函数依赖,那么X → Z
也是有效的。 - 形式化:如果
X → Y
和Y → Z
,则X → Z
。 - 例子:如果
A → B
和B → C
,那么A → C
。
- 如果
根据 Armstrong 公理推导其他规则
除了上述三条基本公理外,Armstrong 公理还可以用来推导其他有用的规则,这些规则可以帮助我们推导出更多的函数依赖关系。常见的推导规则包括
-
合并性(Union):
- 如果
X → Y
和X → Z
都是有效的函数依赖,那么X → Y, Z
也是有效的。 - 形式化:如果
X → Y
和X → Z
,则X → Y, Z
。 - 例子:如果
A → B
和A → C
,那么A → B, C
。
- 如果
-
分解性(Decomposition):
- 若
成立,且
,则
也成立
- 如果
X → Y, Z
是有效的函数依赖,那么X → Y
和X → Z
也都是有效的。&
=>
- 形式化:如果
X → Y, Z
,则X → Y
和X → Z
。 - 例子:如果
A → B, C
,那么A → B
和A → C
。
- 若
-
合成性(Pseudotransitivity):
- 如果
X → Y
和Y, Z → W
都是有效的函数依赖,那么X, Z → W
也是有效的。 - 形式化:如果
X → Y
和Y, Z → W
,则X, Z → W
。 - 例子:如果
A → B
和B, C → D
,那么A, C → D
。
- 如果
范式(Normal Forms, NFs)
在数据库设计中,规范化理论用于减少数据冗余和避免插入、更新和删除异常。规范化的过程是将数据库分解成多个表,并通过范式来衡量数据库设计的质量。范式判断是评估数据库设计是否符合一定规范的过程,主要通过函数依赖来判断一个表是否满足特定的范式。
常见范式和范式判断的标准
-
第一范式(1NF)
- 要求:每个字段(列)都应该是不可再分的原子值(即单一值),不能有重复的列或表。
- 判断标准:如果表中的每一列都是原子值,没有重复组或数组类型的数据,就满足 1NF。
-
第二范式(2NF)
- 要求:表必须满足 1NF,并且所有非主属性完全依赖于主键(即不存在部分依赖)。只有主键是集合属性是才有可能违反第二范式
- 判断标准:首先确保表满足 1NF,然后检查是否存在非主属性依赖于主键的部分属性(即主键的一部分),如果存在,则需要进一步分解表格。
-
第三范式(3NF)
- 要求:表必须满足 2NF,并且所有非主属性直接依赖于主键,不能通过其他非主属性间接依赖主键(即不存在传递依赖)。
- 判断标准:首先检查表是否满足 2NF,然后检查是否有非主属性依赖于其他非主属性,如果存在,表不满足 3NF。
-
博茨-科得范式(BCNF):BCNF是3NF的一个特殊形式。BCNF要求数据库表中的每个决定因素都必须是候选键。换句话说,如果某个非主键字段决定了其他字段的值,那么该字段必须是候选键。
- 要求:表必须满足 3NF,并且每一个非平凡的函数依赖 X → Y 中,X 必须是主键(即左侧属性集必须是主键)。
- 判断标准:检查所有的函数依赖,确保每个决定属性集的左侧属性集是主键。
-
第四范式(4NF):消除多值依赖(MVD, Multivalued Dependency)。如果一个关系模式
中的某个属性集
能够决定多个
值,同时也能决定多个
值,而
和
之间相互独立(彼此无关),那么就存在 多值依赖(MVD)。
- 关系模式要满足 4NF,必须先满足 BCNF,并且不能存在非平凡的多值依赖。
第四范式
示例(未满足 4NF,存在多值依赖)
学号 | 证书 | 课程 |
---|---|---|
1001 | 英语四级 | 数据库 |
1001 | 英语四级 | 计算机网络 |
1001 | 计算机二级 | 数据库 |
1001 | 计算机二级 | 计算机网络 |
分析:
- 学号 →→ 证书(一个学生可以有多个证书)
- 学号 →→ 课程(一个学生可以选修多个课程)
- 但证书和课程之间并无直接关系(学生的证书与选修的课程无关)。
- 多值依赖导致数据冗余,比如"英语四级" 和 "计算机二级" 在数据库和计算机网络课程中重复出现。
解决方案(拆分表)
将表拆分为两个独立的表:
- ✅ 学生-证书表:
- ✅ 学生-课程表:
拆分后,数据冗余被消除,满足 4NF。
规范化的过程
- 从1NF开始:确保每个字段只有单一的值(没有重复的列和多值属性)。
- 应用2NF:消除部分依赖,确保非主键字段完全依赖于主键。
- 应用3NF:消除传递依赖,确保非主键字段不依赖于其他非主键字段。
- 进一步优化:根据需要应用BCNF、4NF和5NF,消除多值依赖和连接依赖。
模式分解
- 是否保持函数依赖
- 是否无损:可以还原
- 无损连接分解:指将一个关系模式分解成若干个关系模式后,通过自然连接和投影等运算仍能还原到原来的关系模式
是否保持函数依赖
无损分解
给定关系模式 和它的子关系模式
,如果通过自然连接操作可以恢复到原始关系
,并且没有丢失任何信息,那么这个分解是无损的。
无损分解表法(分解矩阵法)
如果关系 R 被分解成子关系 R1, R2, ..., Rn,可以构造一个分解矩阵来检查是否无损。
步骤
-
创建矩阵,每一列代表一个属性,每一行代表一个子关系:
- 初始状态:如果属性属于某个子关系 Ri,标记为 Ri,否则标记为 NULL。
-
根据函数依赖更新矩阵:
- 若某一行的某些属性可以通过函数依赖推导出某个属性 X,则用同一行的标记替换 X 的值。
-
检查是否存在一行所有元素仍然唯一:
- 如果某一行的所有列的值都相同(即全为 R1、R2 之一),则无损。
- 否则,有损。
示例
给定关系 R(A, B, C),函数依赖:
分解:
属性 | A | B | C |
---|---|---|---|
R1 | R1 | R1 | NULL |
R2 | NULL | R2 | R2 |
- 根据 A → B,R1 可决定 B,因此 B 变为 R1
- 根据 B → C,R1 可决定 C,因此 C 变为 R1
- 结果:
属性 | A | B | C |
---|---|---|---|
R1 | R1 | R1 | R1 |
R2 | NULL | R2 | R2 |
- 有一整行是 R1,因此是无损分解 ✅
基于函数依赖的无损判定(属性闭包法)
定理: 关系模式 R 在 R1(A1, A2, ...), R2(B1, B2, ...) 上的分解是无损的,当且仅当:
即:
-
公共属性集(
)可以函数依赖地决定至少一个完整的子模式(R1 或 R2)。
- 这样,在 R1 ∪ R2 进行自然连接时,不会产生错误的笛卡尔积。
示例
给定关系 R(A, B, C),函数依赖集:
分解:
验证无损:
- 公共属性 R1 ∩ R2 = {B}
-
检查 B 是否能决定 R1 或 R2:
- B → C ✅(可以决定 R2)
- 因此是无损分解 ✅
总结
方法 | 步骤 | 适用场景 |
---|---|---|
属性闭包法 | 计算 |
适用于 两个子关系的无损判定 |
无损分解表法 | 构造矩阵,利用函数依赖推导,检查是否能合并行 | 适用于多个子关系的无损判定 |
事务(Transaction)
由一组数据库操作组成的逻辑单位,这些操作要么全部执行成功,要么全部撤销(即回滚)。事务的主要目的是为了保证数据库的一致性、完整性以及隔离性。事务处理使得数据库能够在多用户并发访问和系统故障时保持正确的状态。
特性(ACID)
- 原子性(Atomicity):事务中的所有操作要么全部执行(Commit),要么全部不执行,不能只执行其中的一部分。如果事务中的一个操作失败,则整个事务会被回滚(Rollback)。
- 一致性(Consistency):事务必须将数据库从一个一致性状态转换到另一个一致性状态。事务执行前后,数据库的完整性约束应保持不变。
- 隔离性(Isolation):多个事务并发执行时,每个事务应该感觉自己是独占的,即事务执行的中间状态对其他事务不可见。具体的隔离程度可以通过设置事务隔离级别来控制。
- 持久性(Durability):一旦事务提交,事务的结果应当永久保存在数据库中,即使系统发生崩溃或电源断电,数据也应该保持不丢失。
生命周期
事务的生命周期可以分为几个阶段,通常如下所示:
- 开始(Start):事务开始时,数据库管理系统为该事务分配资源,标记事务的开始。
- 执行(Execute):事务中包含的数据库操作(如插入、删除、更新)被执行。如果在执行过程中没有错误,事务继续。
-
提交(Commit):当所有操作都成功执行时,事务会通过提交(
COMMIT
)命令使得对数据库的修改永久生效。 -
回滚(Rollback):如果事务中的某个操作失败,或者在执行过程中发生了错误,事务会通过回滚(
ROLLBACK
)命令撤销所有已执行的操作,恢复到事务开始之前的状态。
并发控制
确保在多个事务并发执行时,数据库的正确性、完整性和一致性得以维持的技术手段。在数据库中,多个事务可能会同时操作相同的数据,这就可能导致数据冲突或不一致的情况,因此需要采用并发控制技术来协调这些事务的执行顺序。
并发控制的基本问题
并发执行的事务可能会导致以下几种问题:
- 丢失更新(Lost Update):当两个事务同时更新同一数据时,其中一个事务的更新可能会被另一个事务覆盖,导致数据丢失。
- 脏读(Dirty Read):事务读取了另一个事务尚未提交的中间数据,这种数据是可能会被回滚的,从而造成不一致。
- 不一致分析(Inconsistent Analysis):事务在读取数据时,某些数据可能被其他事务修改,导致事务读取到的数据不一致。
- 幻读(Phantom Read):在一个事务中,某些数据被读取后,另一个事务对数据进行了插入或删除,导致第一个事务的查询结果发生变化。
并发控制方法
并发控制方法 | 核心思想 | 优点 | 缺点 |
---|---|---|---|
封锁协议 | 通过加锁控制事务访问数据 | 实现简单,隔离性强 | 可能导致死锁,锁开销大 |
时间戳排序 | 根据时间戳决定事务执行顺序 | 避免死锁,适合高并发 | 事务可能频繁重启 |
多版本并发控制(MVCC) | 维护数据多个版本,事务读取旧版本数据 | 读写不冲突,适合读多写少 | 需要额外存储空间,版本链可能过长 |
乐观并发控制 | 假设冲突少,提交时检查冲突 | 避免锁开销,适合低冲突场景 | 高冲突场景下性能差 |
基于有效性检查 | 提交时检查事务读写集是否冲突 | 实现简单,适合低冲突场景 | 高冲突场景下性能差 |
封锁协议
通过对数据加锁,限制其他事务对同一数据的访问,确保事务隔离性。
1. 锁的种类
-
共享锁(S Lock)
- 允许多个事务读取同一数据项,但不允许修改。
- 共享锁可以同时存在多个,但一个共享锁和一个排他锁是互斥的。
-
排他锁(X Lock)
- 排他锁允许事务读取并修改数据,但在锁定期间,其他事务无法访问该数据。
- 事务在修改数据之前必须获得排他锁。
2. 常见的封锁协议
在数据库并发控制中,封锁协议(Locking Protocol)用于确保事务的隔离性和一致性。常见的封锁协议包括一级封锁协议、二级封锁协议和三级封锁协议
封锁协议 | 修改数据加锁 | 读取数据加锁 | 解决的问题 | 未解决的问题 |
---|---|---|---|---|
一级封锁协议 | 排他锁(X锁) | 不加锁 | 脏写 | 脏读、不可重复读、幻读 |
二级封锁协议 | 排他锁(X锁) | 共享锁(S锁) | 脏写、脏读 | 不可重复读、幻读 |
三级封锁协议 | 排他锁(X锁) | 共享锁(S锁) | 脏写、脏读、不可重复读 | 幻读 |
1. 一级封锁协议(First Locking Protocol)
-
核心规则:
- 事务在修改数据时必须加锁,通常使用排他锁(X锁)。
- 事务在读取数据时不需要加锁。
-
解决的问题:
- 避免脏写(Dirty Write)问题,即防止两个事务同时修改同一数据。
-
未解决的问题:
- 脏读(Dirty Read):由于读取数据时不加锁,事务可能读取到未提交的数据。
- 不可重复读(Non-Repeatable Read)和幻读(Phantom Read)。
-
适用场景:
- 对一致性要求较低的场景。
2. 二级封锁协议(Second Locking Protocol)
-
核心规则:
- 事务在修改数据时必须加锁,通常使用排他锁(X锁)。
- 事务在读取数据时也必须加锁,通常使用共享锁(S锁)。
-
解决的问题:
- 避免脏读(Dirty Read)问题,因为读取数据时加共享锁,其他事务无法修改数据。
- 同时避免脏写(Dirty Write)问题。
-
未解决的问题:
- 不可重复读(Non-Repeatable Read):由于共享锁在读取完成后立即释放,其他事务仍可能修改数据。
- 幻读(Phantom Read)。
-
适用场景:
- 对一致性要求较高的场景,但允许不可重复读和幻读。
3. 三级封锁协议(Third Locking Protocol)
-
核心规则:
- 事务在修改数据时必须加锁,通常使用排他锁(X锁)。
- 事务在读取数据时也必须加锁,通常使用共享锁(S锁)。
- 共享锁(S锁)必须保持到事务结束(即事务提交或回滚)才释放。
-
解决的问题:
- 避免脏读(Dirty Read)和不可重复读(Non-Repeatable Read)问题。
- 由于共享锁保持到事务结束,其他事务无法在事务执行期间修改数据。
-
未解决的问题:
- 幻读(Phantom Read):其他事务仍可能插入新数据,导致当前事务读取到新的记录。
-
适用场景:
- 对一致性要求非常高的场景,但允许幻读。
4. 与两阶段加锁(2PL)的关系
- 上述封锁协议可以结合两阶段加锁(2PL)使用,以实现更严格的隔离性(如可串行化)。
-
两阶段加锁要求事务分为两个阶段:
- 扩展阶段(Growing Phase):事务可以申请锁,但不能释放锁。
- 收缩阶段(Shrinking Phase):事务可以释放锁,但不能申请锁。
- 结合两阶段加锁后,封锁协议可以解决幻读问题,并实现可串行化隔离级别。
时间戳排序(Timestamp Ordering)
时间戳排序通过为每个事务分配唯一的时间戳,并根据时间戳决定事务的执行顺序。
核心规则
- 每个事务在开始时分配一个唯一的时间戳。
- 事务对数据的读写操作必须按照时间戳的顺序执行。
- 如果事务尝试访问已被更新(或锁定)的数据,则会被中止并重新启动。
优点
- 避免死锁问题,因为事务不会等待锁。
- 实现简单,适合高并发场景。
缺点
- 可能导致事务频繁重启,降低性能。
- 无法完全解决幻读问题。
3. 多版本并发控制(MVCC, Multi-Version Concurrency Control)
MVCC通过维护数据的多个版本来实现并发控制,允许多个事务同时读取和修改数据。
核心思想
- 每次修改数据时,生成一个新的版本,而不是直接覆盖旧数据。
- 每个事务只能看到在其开始之前已提交的数据版本。
优点
- 读操作不会阻塞写操作,写操作也不会阻塞读操作。
- 支持高并发,适合读多写少的场景。
缺点
- 需要额外的存储空间来维护数据版本。
- 可能导致版本链过长,影响性能。
实现
- PostgreSQL:使用 MVCC 作为默认并发控制机制。
- MySQL(InnoDB):也支持 MVCC。
死锁处理(Deadlock Handling)
死锁是指多个事务相互等待对方释放锁,导致所有事务无法继续执行。
死锁预防
- 顺序加锁:要求事务按照固定的顺序加锁。
- 超时机制:事务等待锁的时间超过阈值时,自动回滚。
死锁检测与恢复
- 等待图(Wait-for Graph):检测事务之间的循环等待。
- 回滚事务:选择一个事务回滚,解除死锁。
数据库设计过程
1. 需求分析阶段
目标
- 理解需求:收集和分析用户需求,明确数据库应该支持的业务流程和功能。
- 确定数据需求:确定系统需要存储的数据类型、数据之间的关系,以及数据的访问方式和使用模式。
任务
- 与用户和业务相关人员进行沟通,了解系统的业务流程和数据需求。
- 确定系统功能、性能、容量等方面的需求。
- 识别关键实体、属性和关系,为后续设计提供基础。
输出
- 数据流图
- 数据字典:列出所有实体、属性、关系的详细定义。
- 需求规格说明书:包括数据需求、功能需求、性能需求等。
2. 概念结构设计阶段
目标
- 创建高层次的抽象数据模型:通过一个概念性的数据模型(通常是ER模型,实体-关系模型),表示系统中的实体、属性和实体间的关系。
任务
- 根据需求分析阶段的结果,确定数据库中包含哪些实体、属性和实体间的关系。
- 使用ER图(实体-关系图)或UML类图等工具来表示系统的概念性结构。
- 实体(Entity):系统中的对象或事物,如“客户”、“订单”等。
- 属性(Attribute):实体的具体特征或属性,如“客户姓名”、“订单日期”等。
- 关系(Relationship):实体之间的联系,如“客户下订单”。
输出
- 概念模型:通常是ER图或类似图表,明确数据库的实体、属性和关系。
- 数据字典:列出所有实体、属性、关系的详细定义。
ER图(实体-关系图,Entity-Relationship Diagram)
ER图是一种用于表示实体及其之间关系的图形化工具,广泛应用于数据库的概念设计阶段。
ER图的基本构成要素:
-
实体(Entity)
- 实体通常表示一个对象或事物,可以是物理的或抽象的。例如,"学生"、"课程"、"订单"等都是实体。
- 实体在ER图中通常用矩形表示。
-
属性(Attribute)
- 属性是描述实体特征的细节,例如,学生实体可能有属性 "学号"、"姓名"、"年龄"等。
- 属性用椭圆形表示,并通过线条与相应的实体连接。
-
关系(Relationship)
- 关系描述不同实体之间的相互联系。例如,“学生选课”表示学生和课程之间的关系。
- 关系用菱形表示,并通过线条连接相关的实体。
-
主键(Primary Key)
- 主键是唯一标识实体的属性。它用来确保每个实体在表中的唯一性。通常在ER图中,用下划线表示主键。
-
联系的基数(Cardinality)
- 基数描述了两个实体之间关系的数量限制,通常有:
- 1对1:一个实体实例只能与另一个实体实例相关。
- 1对多:一个实体实例可以与多个实体实例相关,但每个多方实例只能与一个实体实例相关。
- 多对多:多个实体实例之间可以有多重关系。
- 基数描述了两个实体之间关系的数量限制,通常有:
-
弱实体(Weak Entity)
- 弱实体是依赖于另一个实体(通常是强实体)存在的实体。例如,"订单项"可能是一个弱实体,它依赖于"订单"实体来唯一标识。
- 弱实体用双矩形表示,并与强实体通过双线连接。
-
多值属性(Multivalued Attribute)
- 多值属性是指一个实体可以具有多个值
联系类型(Cardinality)
在ER图中,联系类型(Cardinality)描述了两个实体之间的关系数量,即它们如何互相关联。判断联系类型通常依赖于实体间关系的基数,即每个实体实例如何与另一个实体实例关联。
1. 一对一(1:1)关系
在一对一关系中,一个实体实例只与另一个实体实例相关联。
举例:一名员工只能拥有一个办公室,一个办公室只能被一名员工占用。
ER图表示:两个实体之间通过一条直线连接,且通常会在连接线上标明"1"。
-
判断标准:
- 如果一个实体实例A与实体实例B之间存在1对1的关系,意味着每个A实体只能关联一个B实体,并且每个B实体也只能关联一个A实体。
2. 一对多(1:N)关系
在一对多关系中,一个实体实例可以与多个另一个实体实例相关联,但另一个实体实例只能与一个实体实例相关联。
举例:一名教授可以教授多门课程,但每门课程只能由一名教授教授。
ER图表示:实体A和实体B之间通过一条线连接,在A的端标记"1"(一方),在B的端标记"N"(多方)。
-
判断标准:
- 如果实体A的每个实例可以关联多个实体B的实例,而实体B的每个实例只能关联实体A的一个实例,则为一对多关系。
3. 多对多(M:N)关系
在多对多关系中,多个实体实例可以与多个另一个实体实例相关联。
举例:学生和课程之间的关系,学生可以选修多门课程,每门课程也可以有多个学生选修。
ER图表示:两个实体之间通过菱形(关系)连接,关系的两端通常标有"M"和"N"。
-
判断标准:
- 如果实体A和实体B之间的每个实例都可以与多个对方实体实例相关联,则为多对多关系。
集成
方法
- 多个局部ER图一次集成
- 逐步集成,用累加的方式一次集成两个局部ER图
集成冲突
- 属性冲突:包括属性域冲突和属性取值冲突
- 命名冲突:包括同名异义和异名同义(同一实体)
- 结构冲突:包括同一对象在不同应用中具有不同地抽象,以及同一实体在不同局部ER图中所包含的属性个数和属性排列次序不完全相同
3. 逻辑结构设计阶段
目标
- 转化为逻辑数据模型:将概念模型转化为逻辑模型,适应具体的数据库管理系统(DBMS)。逻辑设计是数据库的结构化描述,通常独立于具体的DBMS。
- 在此阶段进行了关系规范化,关系规范化的目的是消除数据冗余和避免数据异常(如插入、更新和删除异常),确保数据的一致性和完整性
任务
-
选择数据模型
- 根据业务需求选择合适的数据模型(如关系模型、文档模型、键值模型等)。在关系型数据库中,选择的是关系模型,在非关系型数据库中,可能选择文档模型、图数据库模型等。
-
定义关系(表)和属性(列)
- 通过ER图(实体-关系图)等工具,明确实体(表)、属性(列)及其之间的关系。
- 确定每个表中所包含的字段,确定每个字段的数据类型(如整数、字符串、日期等)。
-
确定主键与外键
- 为每个表选择主键(Primary Key),以确保记录的唯一性。
- 确定外键(Foreign Key)以建立表与表之间的联系,确保数据的参照完整性。
-
定义完整性约束
- 定义实体完整性、参照完整性、域完整性等约束,以确保数据的一致性和完整性。
- 可以包括主键约束、外键约束、唯一约束、检查约束等。
-
规范化
- 对数据模型进行规范化(Normalization),通过分解关系(表)来消除冗余数据,减少数据异常,确保数据的存储效率和一致性。
- 规范化的过程一般包括从第一范式(1NF)到第三范式(3NF)的规范化步骤,也可能包括更高的范式。
-
确定数据表的关系
- 确定不同数据表之间的关系,如一对多关系、多对多关系等。
输出
- 逻辑数据模型:通常是关系模型,包括所有的表、字段及其关系。
- 规范化模型:模型中数据已被规范化,符合至少第三范式(3NF)标准。
ER图转换关系模式
1. 将每个实体转换为关系
每个实体集(Entity Set)对应于一个关系模式(即数据库中的表)。实体集中的每个属性将转化为关系中的列。
- 实体转化为表:实体的每个属性成为表中的一列。
- 主键:ER图中每个实体的主键属性变为关系表的主键。
2. 将每个关系转换为关系模式
每个关系(Relationship)对应于关系模型中的表。关系集转换为关系模式时,需要根据关系的基数(Cardinality)选择合适的方式来表示。
- 一对一关系(1:1):在关系模式中,可以将两个实体表中的主键互为外键,或将一个实体表中的主键作为另一个实体的外键。
- 一对多关系(1:N):“一方”表的主键会作为外键添加到“多方”表中。
- 多对多关系(M:N):创建一个新的关系表,这个表包含两个外键,分别指向参与关系的两个实体表的主键。
3. 处理属性
- 如果一个属性是复合属性(Composite Attribute),则它将被拆解为多个原子属性。例如,地址可以拆分为“街道”、“城市”、“邮政编码”等。
- 如果是多值属性(Multivalued Attribute),需要创建一个新的关系表,将多值属性的每个值与原实体的主键关联。
4. 处理弱实体
弱实体(Weak Entity)依赖于强实体(Strong Entity)的主键,并且通常没有自己的主键。在转换为关系模式时,弱实体表会包含其自身的属性和强实体的主键作为外键。
4. 物理设计阶段
目标
- 优化数据库存储和性能:根据实际的硬件环境和系统需求,设计如何在存储设备中实际存储数据,优化查询性能、存储效率和系统响应时间。
任务
- 选择存储结构:决定数据存储的方式(如如何存储表、索引、视图等)。
- 优化性能:考虑数据的访问方式,合理设置索引,以提高查询效率;同时,考虑数据分区、分片等策略来提升性能。
- 设计数据分布:对于分布式数据库,确定数据如何分布到不同的节点或存储位置。
- 备份与恢复策略:设计如何进行数据库备份和恢复,确保数据的安全性和可用性。
输出
- 物理数据模型:描述数据的物理存储结构和存取方式,包括索引、分区策略、存储路径等。
5. 数据库实施阶段
根据逻辑设计和物理设计阶段的结果建立数据库,编制与调试应用程序,组织数据入库,并进行试运行
6. 数据库运行和维护阶段
数据库应用系统经过试运行即可投入运行,但该阶段需要不断地对系统进行评价、调整与修改
数据库安全
- 数据库的安全机制中,通过提供存储过程第三方开发人员调用进行数据更新,从而保证数据库的关系模式不被第三方所获取
- 存储过程是数据库所提供的一种数据库对象,通过存储过程定义一段代码,提供给应用程序调用来执行
- 从安全性的角度考虑,更新数据时,通过提供存储过程让第三方调用,将需要更新的数据传入存储过程,而在存储过程内部用代码分别对需要的多个表进行更新,从而避免了向第三方提供系统的表结构,保证了系统的数据安全
备份与恢复技术
数据库备份的重要性
- 数据保护:防止数据丢失。
- 灾难恢复:在灾难事件后恢复数据。
- 合规性:满足法律法规对数据保留和恢复的要求。
- 业务连续性:减少停机时间,确保业务正常运行。
物理备份类型
特性 | 冷备份(Cold Backup) | 热备份(Hot Backup) |
---|---|---|
数据库状态 | 关闭 | 运行 |
数据一致性 | 高 | 需要额外机制(如日志)保证一致性 |
业务影响 | 数据库不可用 | 数据库可用 |
复杂性 | 简单 | 复杂 |
适用场景 | 小型数据库、允许停机的系统 | 大型数据库、高可用性系统 |
冷备份(Cold Backup)
冷备份是在数据库关闭或停止运行的状态下进行的备份。备份内容包括数据库的数据文件、日志文件、控制文件等。
-
优点:
- 备份过程简单,数据一致性高。
- 不需要额外的日志或锁机制。
-
缺点:
- 数据库在备份期间不可用,影响业务连续性。
- 不适合需要高可用性的场景。
-
适用场景:
- 小型数据库或允许停机的系统。
- 定期维护期间的备份。
热备份(Hot Backup)
热备份是在数据库运行状态下进行的备份。备份过程中数据库可以继续提供服务。
-
优点:
- 数据库在备份期间可用,不影响业务连续性。
- 适合高可用性要求的场景。
-
缺点:
- 备份过程复杂,需要数据库支持(如Oracle的热备份模式)。
- 可能需要额外的日志或锁机制来保证数据一致性。
-
适用场景:
- 大型数据库或需要24/7高可用性的系统。
- 在线业务系统。
数据备份类型
备份类型 | 特点 | 优点 | 缺点 | 适用场景 |
---|---|---|---|---|
完全备份(Full Backup) | 备份整个数据库,包括所有数据和对象。 | - 恢复简单,只需一个备份文件。 - 适合首次备份和灾难恢复。 |
- 备份时间长。 - 占用存储空间大。 |
首次备份、定期全量备份(如每周一次)。 |
增量备份(Incremental Backup) | 仅备份自上次备份以来发生变化的数据。 | - 备份速度快。 - 占用存储空间小。 |
- 恢复时需要依次应用完全备份和所有增量备份。 - 恢复时间较长。 |
频繁备份(如每天一次)。 |
差异备份(Differential Backup) | 备份自上次完全备份以来发生变化的数据。 | - 恢复时只需应用完全备份和最新的差异备份。 - 恢复时间较短。 |
- 备份文件比增量备份大。 - 占用存储空间较多。 |
中等频率备份(如每两天一次)。 |
事务日志备份(Transaction Log Backup) | 备份事务日志,记录所有数据库操作(如插入、更新、删除)。 | - 支持点-in-time恢复(恢复到特定时间点)。 - 适合高可用性数据库。 |
- 需要定期清理日志文件,否则可能占用大量空间。 - 管理复杂。 |
高可用性数据库(如SQL Server、Oracle)。 |
- 日志文件:事务日志是针对数据库改变所做的记录,它可以记录针对数据库的任何操作,并将记录结果保存在独立的文件中
备份策略
完全备份 + 增量备份
- 每周进行一次完全备份,每天进行一次增量备份。
- 优点:节省存储空间。
- 缺点:恢复时间较长。
完全备份 + 差异备份
- 每周进行一次完全备份,每两天进行一次差异备份。
- 优点:恢复时间较短。
- 缺点:占用存储空间较大。
完全备份 + 事务日志备份
- 每周进行一次完全备份,每小时进行一次事务日志备份。
- 优点:支持点-in-time恢复。
- 缺点:管理复杂,需要定期清理日志。
恢复方法
- 找最近的全部备份
- 找最近的差量备份
- 找差量备份后面的增量备份
- 全部备份 + 差量备份 + 增量备份
数据库故障
数据库故障是指由于硬件、软件、网络或人为原因导致数据库无法正常运行或数据丢失的情况
数据库故障的类型
故障类型 | 恢复方法 | 关键工具或技术 |
---|---|---|
事务故障 | 回滚未完成的事务 | 事务日志 |
系统故障 | 重做已提交的事务,回滚未完成的事务 | 检查点、事务日志 |
介质故障 | 从备份恢复数据,应用日志 | 完全备份、增量备份、事务日志 |
灾难性故障 | 从异地备份恢复数据,启用备用数据中心 | 异地备份、灾难恢复计划(DRP) |
事务故障
单个事务在执行过程中发生错误(如违反约束、死锁、用户中断)。
- 影响:事务无法完成,可能导致数据不一致。
-
恢复方法:
- 回滚(Rollback):撤销事务的所有操作,恢复到事务开始前的状态。处理事务本身的可预期故障(本身逻辑)
- 日志恢复:利用事务日志(Transaction Log)回滚未完成的事务。处理事务本身的不可预期故障(算术溢出、违反存储保护)
系统故障
由于硬件故障、操作系统崩溃或数据库软件错误导致数据库系统停止运行。
- 影响:内存中的数据丢失,但磁盘上的数据通常完好。
-
恢复方法:使用检查点法(系统重启时自动完成)
- 重做(Redo):利用事务日志重新执行已提交但未写入磁盘的操作。正向重做
- 撤销(Undo):回滚未完成的事务。反向还原
介质故障
磁盘损坏或数据文件丢失导致数据库无法访问。
- 影响:磁盘上的数据丢失或损坏。
-
恢复方法:
- 从备份恢复:使用最近的完全备份和增量/差异备份恢复数据。
- 日志恢复:应用事务日志恢复到故障前的状态。
灾难性故障
由于火灾、洪水、地震等自然灾害导致数据库系统完全损坏。
- 影响:数据库服务器和数据中心可能完全无法使用。
-
恢复方法:
- 异地备份恢复:从异地备份恢复数据。
- 灾难恢复计划(DRP):启用备用数据中心或云服务。
性能优化
数据仓库
特点
- 面向对象:数据按主题组织
- 集成的:消除了源数据中的不一致性,提供整个企业的一致性全局信息
- 相对稳定的(非易失的):主要进行查询操作,只有少量的修改和删除操作(或是不删除)
- 反映历史变化(随着时间变化):记录了企业从过去某一时刻到当前各个阶段的信息,可对发展历程和未来做定量分析和预测
嵌入式数据库管理系统
- Embedded DataBase Management System, EDBMS
- 在嵌入式设备上使用的 DBMS
- 由于用到 EDBMS 的嵌入式系统多是移动信息设备,例如:掌上电脑、车载设备等移动通信设备,位置固定的嵌入式设备很少用到,所以,嵌入式数据库又称移动数据库或嵌入式移动数据库
- EDBMS 作用主要是解决移动计算环境下数据的管理问题,移动数据库是移动计算环境中的分布式数据库
- 嵌入式数据库管理系统一般只提供本机服务接口、只为前端应用提供基本的数据支持且支持实时数据的管理
数据挖掘
- Data mining,又称:资料探勘、数据采矿
- 是数据库知识发现(Knowledge-Discovery in Databases, KDD)中的一个步骤
- 指从大量的数据中通过算法搜索隐藏域其中信息的过
- 通过分析每个数据,从大量数据中找寻其规律的技术,主要有数据准备、规律寻找和规律表示3个步骤
步骤
- 数据准备:从相关的数据源中选取所需的数据并整合成用于数据挖掘的数据集
- 规律寻找:用某种方法将数据集所含的规律找出来
- 规律表示:尽可能以用户可理解的方式将找出的规律表示出来
任务
- 关联分析
- 聚类分析
- 分类分析
- 异常分析
- 特异群组分析
- 演变分析
- 关联规则挖掘
知识点
- 两阶段提交协议(保证分布式事务的原子性(Atomicity),确保所有节点要么全部提交,要么全部回滚):表决阶段 & 执行阶段
- 两阶段加锁协议(保证事务的隔离性(Isolation),防止并发冲突):扩展阶段 & 收缩阶段