整理数据库基础理论。
数据库范式
关系数据库有六种范式:第一范式、第二范式、第三范式、巴斯-科德范式(BCNF)、第四范式和第五范式。范式级别越高对数据表的要求越严格。
- 第一范式要求最低,只要求表中字段不可拆分,无重复列
- 第二范式在第一范式的基础上要求每条记录由主键唯一区分,记录中所有属性都依赖于主键。
- 第三范式在第二范式的基础上,要求所有属性必须直接依赖主键,不允许间接依赖。
一般说来,数据库只需满足第三范式就可以了。在某些实际业务场景下,适当的“反范式”设计可能更方便。
数据库事务
事务特性
Atomic,Consistency,Isolation,Durability
- 原子性:事务由原子的操作序列组成,所有操作要么全部成功,要么全部失败回滚。
- 一致性:事务的执行不能破坏数据库数据的完整性和一致性,一个事务在执行之前和执行之后,数据库都必须处以一致性状态。比如在做多表操作时,多个表要么都是事务后新的值,要么都是事务前的旧值。
- 隔离性:多个用户并发访问数据库时,数据库为每个用户执行的事务,不能被其他事务的操作所干扰,多个并发事务之间要相互隔离。
- 持久性:一个事务一旦提交并执行成功,那么对数据库中数据的改变就是永久性的,即便是在数据库系统遇到故障的情况下也不会丢失提交事务的操作。
事务隔离级别
级别 | 脏读 | 不可重复读 | 幻读 |
---|---|---|---|
读未提交 | Y | Y | Y |
读已提交 | N | Y | Y |
可重复读 | N | N | Y |
串行化 | N | N | N |
注:Y/N 表示 是/否 存在对应的隔离级别问题。
事务分类
- 扁平化事务
- 所有的操作都在同一层次,要么都成功,要么都回滚。是平时使用最多的一种事务,
- 带保存点的扁平事务
- 允许事务在执行过程中回滚到较早的状态,而不是全部回滚。
- 通过在事务中插入保存点,当操作失败后,可以选择回滚到最近的保存点处。
- 链事务
- 可以看做是第二种事务的变种。
- 在事务提交时,会将必要的上下文隐式传递给下一个事务,当事务失败时就可以回滚到最近的事务。
- 链事务只能回滚到最近的保存点,而带保存点的扁平化事务是可以回滚到任意的保存点。
- 嵌套事务
- 由顶层事务和子事务构成,类似于树的结构。
- 一般顶层事务负责逻辑管理,子事务负责具体的工作;
- 子事务可以提交,但真正提交要等到父事务提交;
- 如果上层事务回滚,那么所有的子事务都会回滚。
- 分布式事务
- 指分布式环境中的扁平化事务。
分布式事务解决方案
常用分布式事务解决方案有 XA 协议、TCC、消息事务方案,以及阿里 GTS/Fescar(后改名为 Seata) 等。
- XA 协议
- 保证强一致性的刚性事务
- 实现方式有两段式提交和三段式提交
- 两段式提交
- 需要一个事务协调者来保证所有的事务参与者都完成了第一阶段的准备工作
- 如果协调者收到所有参与者都准备好的消息,就会通知所有的事务执行第二阶段提交。
- 一般场景下能够很好地解决分布式事务,然而两阶段在即使只有一个进程发生故障时,也会导致整个系统存在较长时间的阻塞。
- 三段式提交
- 增加 Pre-commit 阶段来减少前面提到的系统阻塞的时间
- 三段式提交很少在实际中使用
- TCC
- 是满足最终一致性的柔性事务方案
- 采用补偿机制,核心思想是对每个操作,都要注册对应的确认和补偿操作
- 分为三个阶段
- Try 阶段主要对业务系统进行检测及资源预留
- Confirm 阶段对业务系统做确认提交
- Cancel 阶段是在业务执行错误,执行回滚,释放预留的资源
- 消息事务
- 使用消息实现一致性的方案
- 将本地操作和发送消息放在一个事务中,保证本地操作和消息发送要么都成功要么都失败
- 下游应用订阅消息,收到消息后执行对应操作。
- 使用消息实现一致性的方案
分库分表
应该尽量多库少表?
准备工作: 表必须有唯一业务id、改造表中的自增id、表必须有唯一索引用于防重
步骤: 历史数据全量同步 增量数据实时同步
rehash、数据染色