0 - 引子
作为一名应用后端开发,工作中最常打交道的关系型数据库非mysql莫属。基本所有业务相关数据都作为一张张表留存在mysql数据库中,这些数据借助其ACID特性安全地躺在硬盘,ssd或别的什么存储介质里。mysql对业务是如此重要,因此后端开发很有必要掌握合理操作mysql的方式。当然,很多开发朋友会说,我会用mysql的,主要就是以下几点:
- 针对需求建表
- 加合适的索引
- 查询时按索引查
- 需要事务保护时开启事务
- 尽量少用join而是放在业务代码里处理
这些我都掌握,我还有必要继续了解mysql吗?这个答案可能因人而异,我是这么理解的:
工具是为了简化流程诞生的,知其然而后合理运用工具以提高效率是基础。如果能知其所以然,那么运用起来会更得心应手,就像相机之于摄影师,高端的摄影师不会局限于几个大众化的参数,其必然对成像原理和手中的相机非常了解,才能为不同场合挑选最合适的参数。
在以上思考的契机下,前日拜读了《mysql技术内幕innodb存储引擎》,该书对最常用存储引擎innodb展开了全面的介绍,不同于网络上零散的知识,其有助于读者将知识串在一起加深理解。本文将对此书内容进行归纳汇总,对我自己也是一次不可多得的复习机会。
1 - mysql体系和存储引擎
mysql的组成
- 连接池组件:和mysql客户端交互,支持tcp/ip,命名管道,共享内存和unix domain socket
- 管理者和管理工具组件:操作各个组件进行管理
- sql 接口组件: 未知,处理DML,DDL等?
- 解析器,优化器,缓存组件:解析查询,挑选执行方案,缓存查询内容
- 存储引擎:插件式,满足不同需求
- 存储介质上的物理文件:持久化数据
有哪些常见存储引擎
- innodb:最常用的存储引擎,支持事务,行锁,面向OLTP
- myISAM:mysql自带的另一个存储引擎,不支持事务,面向OLAP
- memory:内存级数据库
- archive:只新增数据,适合处理归档数据
- ndb:存储集群
上述存储引擎间的部分区别:
存储引擎 | 事务 | 锁粒度 | mvcc | 索引 |
---|---|---|---|---|
innodb | 支持 | 行锁 | 支持 | b+,hash,全文 |
myISAM | 不支持 | 表锁 | 不支持 | b+,全文 |
archive | 不支持 | 行锁 | 支持 | |
memory | 不支持 | 表锁 | 不支持 | b+,hash |
ndb | 不支持 | 行锁 | 支持 | b+,hash |
2 - innodb概述
innodb 构成
后台线程:主要负责执行IO,管理内存池中的数据
- 将赃页持久化
- 将redo log缓冲持久化
- 合并插入缓冲
- 清理undo log
内存池
buffer_pool
- 数据页
- 索引页
- 插入缓冲
- 锁信息
- redo log buffer
- undo log
- 物理文件
buffer_pool中的内存页如何管理
通过LRU保留最新的页,其中有一个优化点:新加入的页只会被放到队列的某个中间位置,以减少热点页被刷出的概率。
redo log buffer
重做日志什么时候产生?
重做日志的内容是?
重做日志不直接写到文件中,而是先写到缓冲再写入文件
写入时机如下:
- 后台线程定时刷入文件
- 事务提交时刷入文件
- 缓冲空间不足一半时,刷入文件
如何保证数据持久化 - Checkpoint
WHY: 突然宕机如何保护内存中还未写入磁盘的赃页数据?
WHAT: checkpoint本质是通过有限的redo log文件大小,来维护最近一次可用存档点,其核心思路是通过同步维护增量更新+异步维护全量更新来完成。(同利用消息队列进行事件缓冲有异曲同工之妙)
HOW:
- write ahead log,事务运行过程,先写redo log,再对页进行修改
- 维护log sequence number,redo log和被修改的页都持有最新的lsn
- 重做日志是循环写入,可能会覆盖之前写入的lsn,在覆盖前,需要将内存中之前的赃页刷入文件
- 当mysql从宕机中恢复时,可以通过redo log来完成数据恢复
关键特性 - 插入缓冲(insert buffer, delete buffer, purge buffer)
WHY: 辅助索引的插入不是顺序的,需要离散地访问辅助索引页,为了避免这种离散访问,临时将索引放在插入缓冲中。需要满足以下几个条件:
- 是辅助索引
- 不是唯一索引
- 待插入索引页不在内存中
HOW: 插入缓冲存放在一个全局b+树中,在以下几个节点会合并到索引页上:
- 索引页被读到内存中
- 索引页空间不足
- 后台线程定时合并
关键特性 - 两次写
WHY: 避免宕机时,中断正在写入的过程,导致一个页部分写入失败,造成数据损坏
HOW: 刷入磁盘时,并不直接写入磁盘中,而是先写入双写缓冲中,待缓冲写满,先将缓冲顺序写入一个缓冲文件,再将数据离散地写入。
关键特性 - 自适应哈希
根据查询情况,对热点数据自适应建立临时哈希索引
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。