数据库 基础
整理了下网上关于数据库的一些IDEA ..
三大范式
第一范式 :
所谓第一范式(1NF)指的是在关系模型中,对列添加的一个规范要求,所有的列都应该是原子性的,即数据库表的每一列都是不可分割的原子数字项,而不是集合、数组、记录等非原子数据项。
虽然第一范式要求各列要保存原子性,不能再分,但是这种要求和我们的需求是相关联的。
第二范式 :
所谓第二范式(2NF)指的是在(1NF)的基础上,非Key属性必须完全依赖于主键,要求实体的属性完全依赖于主关键字。
所谓完全依赖是指不能存在仅依赖主关键字一部分的属性,如果存在,那么这个属性和主关键字的这一部分应该分离出来形成一个新的实体,新实体与原实体之间是一对多的关系。
第三范式 :
第三范式(3NF)的目标就是确保表中各列与主键列直接相关,而不是间接相关。即各列与主键列都是一种直接依赖关系,则满足第三范式。
第三范式的目标就是确保表中各列与主键列直接相关,而不是间接相关。即各列与主键列都是一种直接依赖关系,则满足第三范式.
总结:
1NF: 字段是最小的的单元不可再分
2NF:满足1NF,表中的字段必须完全依赖于全部主键而非部分主键 (一般我们都会做到),一张表的字段必须是跟主键相关的,不把无关数据放进来。
3NF:满足2NF,非主键外的所有字段必须互不依赖,就是各种信息只在一个地方存储,不出现在多张表中。
4NF:满足3NF,消除表中的多值依赖。
事务
特性 | 说明 |
---|---|
原子性 Atomic | 表示组成一个事务的多次数据库操作是一个不可分割的原子单元,只有所有的操作都执行成功,才提交整个事务 。 事务中的任何一次数据库操作失败,已经执行操作都必须回滚,让数据库返回到操作前的状态 |
一致性 Consistency | 事务操作后,数据库所处的状态和它的业务规则是一致的 。比如 A 账户转账到 B 账户,不管操作是否异常, A 账户与 B 账户的总额是不变的。 |
隔离性 Consistency | 在并发操作数据时,不同的事务拥有各自的数据空间,它们的操作既可能地不对对方产生干扰。数据库规定了多种事务隔离级别,不同的隔离级别对应不同的干扰程度 。 隔离级别越高,数据一致性越好,但并发性越差。 |
持久性 Durability | 一旦事务提交成功,事务中所有的数据都必须被持久化到数据库中 。 即使在提交事务后数据库发生崩溃,那么当数据库重启时,也必须保证能够根据日志恢复数据 。 |
并发性
数据库中的相同数据,可能同时被多个事务所访问。所以,如果没有采取必要的隔离措施,就会导致各种并发问题,从而破坏数据的完整性 。
并发问题可以归结为 5 类,包括 3 类数据读问题(脏读 、 不可重复度 、 幻读)和 2 类数据更新问题(第一类丢失更新和第二类丢失更新)。
1 脏读
A 事务读取了 B 事务尚未提交的更改数据,并在此数据的基础上进行操作 。 如果此时 B 事务回滚,那么 A 事务之前读到的数据就是脏数据。
时间序列 | 事务 A | 事务 B |
---|---|---|
1 | 开始事务 | 开始事务 |
2 | - | 查询账户余额(100 元) |
3 | - | 取出 50 元 |
4 | 查询账户余额(50 元)【脏读】 | - |
5 | - | 回滚事务(账户余额:100 元) |
6 | 存入 100 元 | - |
7 | 提交事务(账户余额:150 元) | - |
这里因为发生脏读,导致账户损失了 50 元(事务 A 存款 100 元,事务 B 无影响,再加上原来的账户余额 100 元,最后的账户余额应该是 200 元才是)。
2 不可重复读
不可重复读指的是事务在不同的时间点,读取到的数据不同。
时间序列 | 事务 A | 事务 B |
---|---|---|
1 | 开始事务 | 开始事务 |
2 | - | 查询账户余额(100 元) |
3 | 查询账户余额(100 元) | - |
4 | - | 取款 10 元 |
5 | - | 提交事务(账户余额:90 元) |
6 | 查询账户余额(90 元) | - |
在时间序列 6,与在时间序列 3 时查询到的余额不同,发生不可重复读现象。
3 幻读
幻象读一般发生在计算统计数据的事务中 。 A 事务读取了 B 事务提交的新增数据,这时 A 事务将出现幻象读的问题 。
假设在同一个事务中,两次统计名某银行支行所有账户的总金额,在两次统计过程中,刚好新增了一个存款账户 。那么,这两次统计的总金额肯定会不一致 。
时间序列 | 事务 A | 事务 B |
---|---|---|
1 | 开始事务 | 开始事务 |
2 | 统计(总金额:10 w) | - |
3 | - | 新增存款账户(金额:1 w) |
4 | - | 提交事务(总金额:11 w) |
5 | 统计(总金额:11 w)幻读 | - |
4 不可重复读与幻读比较
比较 | 不可重复读 | 幻读 |
---|---|---|
读取对象 | 读到其它事务已经提交的修改或删除数据。 | 读到其它事务已经提交的新增数据。 |
采取措施 | 对所要操作的数据添加行级锁,避免这些数据发生变化。 | 对所要操作的数据所在表添加表级锁,即将整张表锁定(在 Oracle 中,是以多版本数据的方式实现的)。 |
5 第一类丢失更新
A 事务回滚时,把 B 事务中已经提交的更新数据给覆盖咯 。
时间序列 | 事务 A | 事务 B |
---|---|---|
1 | 开始事务 | 开始事务 |
2 | 查询账户余额(100 元) | - |
3 | - | 查询账户余额(100 元) |
4 | - | 取款 10 元 |
5 | - | 提交事务(账户余额:90 元) |
6 | 存入 10 元 | - |
7 | 提交事务(账户余额:110 元) | - |
这个问题影响很大。这个例子中,账户余额应该还是 100 元(取款 10 元,存入 10 元,实际对账户无影响),但因为存在第一类丢失更新,导致银行损失 10 元。如果事务 A 先提交,那么账户将损失 10 元。
6 第二类丢失更新
A 事务提交后覆盖了 B 事务已经提交的数据,导致 B 事务所做操作丢失。
时间序列 | 事务 A | 事务 B |
---|---|---|
1 | 开始事务 | 开始事务 |
2 | - | 查询账户余额:100 元 |
3 | 查询账户余额:100 元 | - |
4 | - | 取款 10 元 |
5 | - | 提交事务(账户余额:90 元) |
6 | 存款 10 元 | - |
7 | 提交事务(账户余额:110 元) | - |
上述示例,直接导致银行损失 10 元。如果 A 事务先提交,那么将导致账户损失 10 元。
本作品采用《CC 协议》,转载必须注明作者和本文链接