1 存储引擎
存储引擎主要有: 1. MyIsam , 2. InnoDB, 3. Memory, 4. Archive, 5. Federated
1.1 InnoDB(B+树):InnoDB 底层存储结构为B+树, B树的每个节点对应innodb的一个page,page大小是固定的, 一般设为 16k。其中非叶子节点只有键值,叶子节点包含完成数据。
- 适用场景:
- 经常更新的表,适合处理多重并发的更新请求。
- 支持事务。
- 可以从灾难中恢复(通过 bin-log 日志等)
- 外键约束。只有他支持外键
- 支持自动增加列属性 auto_increment。
1.2 MyIASM
- MyIASM 是 MySQL 默认的引擎,但是它没有提供对数据库事务的支持,也不支持行级锁和外键, 因此当 INSERT(插入)或 UPDATE(更新)数据时即写操作需要锁定整个表,效率便会低一些。
- MyISAM 执行读取操作的速度很快,而且不占用大量的内存和存储资源。在设计之初就预想数据组织 成有固定长度的记录,按顺序存储的。---ISAM 是一种静态索引结构。缺点是它不支持事务处理。
1.3 Memory
- Memory(也叫 HEAP)堆内存:使用存在内存中的内容来创建表。每个 MEMORY 表只实际对应 一个磁盘文件。MEMORY 类型的表访问非常得快,因为它的数据是放在内存中的,并且默认使用 HASH 索引。但是一旦服务关闭,表中的数据就会丢失掉。 Memory 同时支持散列索引和 B 树索 引,B树索引可以使用部分查询和通配查询,也可以使用<,>和>=等操作符方便数据挖掘,散列索 引相等的比较快但是对于范围的比较慢很多。
2 索引(帮助 MySQL 高效获取数据的数据结构)
常见的查询算法,顺序查找,二分查找,二 叉排序树查找,哈希散列法,分块查找,平衡多路搜索树 B 树(B-tree)
- 1. 唯一性索引的值是唯一的,可以更快速的通过该索引来确定某条记录。
- 2. 为经常需要排序、分组和联合操作的字段建立索引:
- 3.为常作为查询条件的字段建立索引。
- 4.限制索引的数目: 越多的索引,会使更新表变得很浪费时间。 尽量使用数据量少的索引
- 5.如果索引的值很长,那么查询的速度会受到影响。 尽量使用前缀来索引
- 6.删除不再使用或者很少使用的索引
- 7 . 最左前缀匹配原则,非常重要的原则。
- 8. 尽量选择区分度高的列作为索引,区分度的公式是表示字段不重复的比例
- 9 . 索引列不能参与计算,保持列“干净”:带函数的查询不参与索引。
- 10. 尽量的扩展索引,不要新建索引。
3 数据库三范式
第一范式(1st NF -列都是不可再分)
第二范式(2nd NF-每个表只描述一件事情)
第三范式(3rd NF- 不存在对非主键列的传递依赖)顾客姓名依赖于非主键顾客编号
4 数据库事务
ACID
5 数据库并发策略
乐观锁和悲观锁以及时间戳
- 时间戳原理:(每次读出来的时候,把该字 段也读出来,当写回去的时候,把该字段加 1,提交之前 ,跟数据库的该字段比较一次,如果比数 据库的值大的话,就允许保存,否则不允许保存)
6 数据库锁
行级锁,表级锁,页级锁
7 分库分表
垂直切分和水平切分两种
8 两阶段提交协议
- 准备阶段:事务协调者(事务管理器)给每个参与者(资源管理器)发送 Prepare 消息,在本地执行事务,写本地的 redo 和 undo 日志,但不提交(先锁定资源)。
- 提交阶段:如果协调者收到了参与者的失败消息或者超时,直接给每个参与者发送回滚(Rollback)消息(根据undo日志回滚);否则, 发送提交(Commit)消息;参与者根据协调者的指令执行提交或者回滚操作,释放所有事务处理过程中使用的锁资源。(注意:必须在最后阶段释放锁资源)
经验:
磁盘的顺序写性能比内存的写性能差不了多少;
在数据库的世界里,数据从来都不重要,日志才是最重要的,有了日志就有了一切;
日志的重要性:先持久化日志的策略叫做Write Ahead Log,即预写日志;
how?
- undo日志用于记录事务开始前的状态,用于事务失败时的回滚操作;redo日志记录事务执行后的状态,用来恢复未写入data file的已成功事务更新的数据。
- 例如某一事务的事务序号为T1,其对数据X进行修改,设X的原值是5,修改后的值为15,那么
- Undo日志为;
- Redo日志为;
事务执行的各个阶段:
- (1)写undo日志到log buffer;;
- (2)执行事务,并写redo日志到log buffer;;
- (3)如果innodb_flush_log_at_trx_commit=1,则将redo日志写到log file,并刷新落盘。
- (4)提交事务。 // 如果innodb_flush_log_at_trx_commit=1并且数据commit后宕机,重启后一定可以根据redo 日志文件恢复数据;
why?
几种异常情况:
- innodb_flush_log_at_trx_commit=2(innodb_flush_log_at_trx_commit和sync_binlog参数详解)时,将redo日志写入logfile后,为提升事务执行的性能,存储引擎并没有调用文件系统的sync操作,将日志落盘。如果此时宕机了,那么未落盘redo日志事务的数据是无法保证一致性的。
- undo日志同样存在未落盘的情况,可能出现无法回滚的情况。
what?
- 数据库数据存放的文件称为data file;日志文件称为log file;数据库数据是有缓存的,如果没有缓存,每次都写或者读物理disk,那性能就太低下了。数据库数据的缓存称为data buffer,日志(redo)缓存称为log buffer。
checkpoint:
- checkpoint是为了定期将db buffer的内容刷新到data file。当遇到内存不足、db buffer已满等情况时,需要将db buffer中的内容/部分内容(特别是脏数据)转储到data file中。在转储时,会记录checkpoint发生的”时刻“。在故障回复时候,只需要redo/undo最近的一次checkpoint之后的操作。
8.2 两阶段提交协议缺点
- 1 同步堵塞,所有的节点,获取资源最后释放;
- 2 单点故障,协调者堵塞,所有参与者都堵塞,协调者重要性;
- 3 数据不一致(脑裂问题),第二个阶段commit过程中,部分节点收到了请求,其余节点没有收到请求,就会出现脑裂问题;// 解决方案 ,补偿
- 4 二阶段无法解决的问题(数据状态不确定)协调者再发出 commit 消息之后宕机,而唯一接收到这条消息的参与者同时也宕机了。那么即使协调者通过选举协议产生了新的协调者,这条事务的状态也是不确定的,没人知道 事务是否被已经提交。// 解决方案,类似zk 先执行同步,一半以上ack后,在通知参与者执行commit请求;
9 三阶段提交协议
改进点:
-
1 引入超时机制。同时在协调者和参与者中都引入超时机制。
-
2 在第一阶段和第二阶段中插入一个准备阶段。保证了在最后提交阶段之前各参与节点的状态是一致的。也就是说,除了引入超时机制之外,3PC 把 2PC 的准备阶段再次一分为二,这样三阶段 提交就有 CanCommit、PreCommit、DoCommit 三个阶段。
-
CanCommit 阶段:协调者向参与者发送 commit 请求,参与者如果可以提交就返回 Yes 响应,否则返回 No 响应。
-
PreCommit 阶段:协调者根据参与者的反应情况来决定是否可以继续进行,有以下两种可能。假如协调者从所有的 参与者获得的反馈都是 Yes 响应,那么就会执行事务的预执行(undo 和 redo 、redo log 数据落盘)。假如有任何一个参与者向协调者发送了No 响应,或者等待超时之后,协调者都没有接到参与者的响应,那么就执行事务的中断。
-
doCommit 阶段:该阶段进行真正的事务提交,主要包含 1.协调者发送提交请求 2.参与者提交事务 3.参与者响应反馈( 事务提交完之后,向协调者发送 Ack 响应。)4.协调者确定完成事务。// 该阶段也有可能脑裂,数据不一致,数据状态不确定,但是概率比二阶段提交协议小很多;
10 柔性事务
- CAP 理论以及 BASE 理论;
- CAP:(一致性、可用性、分 区容忍性)
- BASE:基本可用(Basically Available)、柔性状态(Soft State)、最终一致性 (Eventual Consistency)
柔性事务:两阶段型、补偿型(TCC,SAGA)、异步确保型、最大努力通知型
两阶段型2PC:就是分布式事务两阶段提交,对应技术上的 XA、JTA/JTS。这是分布式环境下事务处理的典型模式。
补偿型:TCC 型事务(Try/Confirm/Cancel)可以归为补偿型。TCC(Try-Confirm-Cancel) 实际上是服务化的两阶段提交协议,业务开发者需要实现这三个服务接口,第一阶段服务由业务代码编排来调用 Try 接口进行资源预留,所有参与者的 Try 接口都成功了,事务管理器会提交事务,并调用每个参与者的 Confirm 接口真正提交业务操作,否则调用每个参与者的 Cancel 接口回滚事务。
补偿型:SAGA事务
- Saga 是一种补偿协议,在 Saga 模式下,分布式事务内有多个参与者,每一个参与者都是一个冲正补偿服务,需要用户根据业务场景实现其正向操作和逆向回滚操作。
- 分布式事务执行过程中,依次执行各参与者的正向操作,如果所有正向操作均执行成功,那么分布式事务提交。如果任何一个正向操作执行失败,那么分布式事务会退回去执行前面各参与者的逆向回滚操作,回滚已提交的参与者,使分布式事务回到初始状态。
- Saga 理论出自 Hector & Kenneth 1987发表的论文 Sagas。
- Saga 正向服务与补偿服务也需要业务开发者实现
异步确保型: 通过将一系列同步的事务操作变为基于消息执行的异步操作, 避免了分布式事务中的同步阻塞操作的影响。
QMQ:(去哪儿网开源)
- begin tx 开启本地事务
- do work 执行业务操作
- insert message 向同实例消息库插入消息
- end tx 事务提交
- send message 网络向 server 发送消息
- reponse server 回应消息
- delete message 如果 server 回复成功则删除消息
- scan messages 补偿任务扫描未发送消息
- send message 补偿任务补偿消息
- delete messages 补偿任务删除补偿成功的消息
最大努力通知型(多次尝试): 这是分布式事务中要求最低的一种, 也可以通过消息中间件实现, 与前面异步确保型操作不 同的一点是, 在消息由 MQ Server 投递到消费者之后, 允许在达到最大重试次数之后正常结束事务。