这是我参与「第五届青训营 」伴学笔记创作活动的第 17 天
SQL
Optimizer优化器
这个优化器是基于规则的优化(RBO Rule Base Optimizer)
我们为什么需要这样一个优化器 ?
因为写SQL代码的是人类,人类往往会写出主观的代码,我们需要使用计算机来辅助优化代码,否则会造成更多的无用功(即搜索复杂化)
对于一个数据库而言,一个查询有着不同的执行方案
对于InnoDB存储引擎来说,全表扫描的意思就是吧聚簇索引中的记录都依次和给定的搜索条件做一下对比,把符合搜索条件的记录加入到结果集,所以需要将聚簇索引对应的页面加载到内存中,然后再检测记录是否符合搜索条件
对于使用二级索引 + 回表方式的查询,设计MySQL的人计算这种查询的成本依赖两个方面的数据:范围区间数量,需要回表的数据量
优化器的功能包括但不限于:
条件优化
把SQl语句精简,做到最简表达式,降低搜索成本
表链接优化
我们总是小表优先进行连接
搜索优化
我们使用唯一索引、普通索引和全表扫描来对搜索进行一定的优化
数据库索引:指的是数据库管理系统中的辅助数据结构,以协助快速查询、更新数据库表中数据。目前数据库中最常用的索引是通过B+树实现的
Atomicity与Undo Log
原子性:一个事务(Transaction)中的所有操作,要么全部完成,要么全部不完成,不会结束在中间的某个环节。事务在执行过程中发生错误,会被恢复(RollBack)到事务开始前的状态,就像这个事务从来没有执行过一样
Undo Log是逻辑日志,记录的是数据的增量变化。利用Undo Log可以进行事务回滚,从而保证事务的原子性。同时也实现了多版本并发控制(MVCC),解决读写冲突和一致性读的问题
Isolation 与 MVCC
MVCC(多版本并发控制)的意义有很多啦
- 读写互不阻塞
- 降低死锁概率
- 实现一致性读
而Undo Log在MVCC中的作用则是
- 每个事务有一个单增德事务ID
- 数据页的记录中包含了DB_ROW_ID,DB_TRX_ID,DB_ROLL_PTR
- DB_ROLL_PTR将数据行的所有快照记录都通过了链表的结构串联起来
这里可以注意到我们需要有一个脏读的概念:
事务还没提交之前,它对数据做的修改,不应当被其他人看到
Durability与Redo Log
如何保证事务结束后,对数据的修改永久保存?
有两个方案
- 方案一:事务提交前页面写盘
- 方案二:WAL(Write-ahead logging),redo log是物理日志,记录的是页面的变化,它的作用是保证事务持久化。如果数据写入磁盘前发生故障,重启MySQL后会根据redo log重做
持久化:事务处理结束后,对数据的修改就是永久的,即便系统故障也不会丢失
WAL:修改并不直接写入到数据库文件中,而是写入到另外一个称为WAL的文件中。如果事务失败,WAL中的记录会被忽略,撤销修改。如果事务成功,它将在随后的某个时间被写回到数据库文件中,提交修改。