本篇文章主要分析一下mysql的内存结构。
介绍
Mysql是最流行的关系型数据库,关系型数据库具有的特点有如下几个:
- 数据以表格的形式存在
- 每行为各种记录数据
- 每列为数据对应的值
- 一个database有若干个表
1.架构图
上图来自Mysql官网Mysql 8.0 InnoDB 架构。咋一看怎么这么复杂?
其实mysql为了提高读写能力,设计了一个Buffer Pool,在写满或者提交的时候才进行刷盘,同时防止突然宕机,又将日志写入了Redo Log。
1.1 Buffer Pool
缓存区大小,达到默认大小128M后进行刷盘操作,服务器资源条件允许的话可以设置大一点。
show global variables like '%innodb_buffer_pool%'
innodb_buffer_pool_size 134217728/1024/1024 #默认128M
缓存区回收机制:LRU算法,HashMap加双向链表,key对应链表的下标
整个Buffer pool一个双向链表架构,分为热数据区(5/8)和冷数据区(3/8),从而来实现回收算法。
在双向链表中,存储的是数据页的指针,方便快速取值。
冷热数据区规则,查询一遍数据后会先加载到冷数据区,如果再次使用过冷数据区前面的数据,就会加入到热数据区。
1.2 Change Buffer
它是Buffer Pool的一部分,当使用某个数据的时候,如果该数据不是唯一索引,不存在数据重复的情况,也就不需要从磁盘加载索引来判断数据是否重复,这种数据就可先把修改记录在内存的Change Buffer缓冲池中,从而提升语句的执行速度。
show global variables like '%innodb_change_buffer%'
1.3 Log Buffer
Buffer Pool数据并不会直接同步到磁盘,也还是会先进入Log Buffer,由刷盘缓冲区根据刷盘时机进行刷盘,默认1
show global variables like '%innodb_flush_log_at_trx_commit%'
- 0:每秒刷新缓存和磁盘
- 1:提交事务后刷
- 2:提交事务刷到操作系统缓存缓冲区,由系统每秒去刷
1.4 ibdata1表空间
主要存储相关的系统信息区
Doublewrite Buffer:双写缓冲,解决不同数据存在不同的页上,随机IO写入时出现故障而没法恢复的问题。
顺序IO和随机IO,磁盘时高速运转的,如果在数据寻址是都寻到的是一个扇区,这就叫顺序IO,如果数据分布在不同的扇区上,就是随机IO,需要多次寻址。
1.5 Undo Log
开启事务时记录事务发生之前的数据状态,发生异常则回滚,保证原子性
show global variables like '%innodb_undo%'
1.6 Redo Log
InnoDB独有,大小默认是48M,两个文件循环写入,前面的内容会被覆盖,一旦写满会触发Buffer pool刷盘,主要是记录了“在某个数据上做了什么修改”。属于物理日志,为innoDB提供了奔溃恢复的特性,实现了持久性。
show global variables like '%innodb_log%'
innodb_log_file_size 50331648/1024/1024=48 #默认48M
1.7 bin log
mysql所有的引擎都支持开启binlog日志,以事件的形式记录了所有的执行语句,可以用来做主从复制和数据恢复。
//查看bin log信息
show variables like '%log_bin%';
默认是关闭的,怎么开启使用会在后续文章中记录。
1.8 File-Per-Table 表文件表空间
表空间,每个表都有单独的表文件。在data目录下可以看到。库名文件下会有对应的表文件user.ibd和user.frm
//查看data目录
show global variables like '%datadir%'
1.9 General Tablespaces通用表空间
通用表空间为通过create tablespace语法创建的共享表空间。其可以容纳多张表,且其支持所有的行格式。
create table tab_name ... tablespace [=] tablespace_name
或
alter table tab_name tablespace [=] tablespace_name
1.10 Temporary Tablespace临时表空间
由于查询或者手动创建的临时表,会创建于ibtemp1文件中,mysql关闭或者初始化时都会临时表空间文件都会被自动移除或者重新创建。
2.InnoDB为什么还要加一个Redo Log
首先了解从磁盘加载数据页
操作系统的一个Page页为4KB,innoDB一个Page页是16KB,在执行的过程中肯定不可能每次都去磁盘中查找,为了提高性能引入内存缓冲区Buffer Pool,也就是说插入更新的数据会先在内存中,达到一定的大小才会触发指定规则后由后台系统线程进行刷盘。
缺点
服务重启或者宕机,数据会丢失。
在此情景下新增了Redo Log保证内存数据的安全性,延迟刷盘的时机,提升吞吐量
Redo Log作用:
1.为InnoDB提供了奔溃恢复的特性,实现持久性
2.Redo Log记录了每个数据页做了什么操作,属于物理日志
3.大小固定,默认48M,前面的内容会被覆盖,一旦写满会触发Buffer Pool刷盘
3.分析一下一条事务的更新语句的执行过程
update xxx set status=1 where id =1
1.事务开始,从内存中(Buffer Pool)或者磁盘中(data file)取出这条数据的数据页。
2.执行器修改数据页中这一条数据的status=1
3.记录status=0(原始值)到Undo Log,记录该log的状态为Prepare
4.记录status=1到Redo Log,记录该log的状态为Prepare
5.调用存储引擎,记录数据页到Buffer Pool,修改status=1
6.如果开启了bin log,写入bin log日志
7.事务提交
8.将Undo Log和Redo Log里面相关的日志状态修改为commit
log这块会保证两阶段提交,奔溃后事务处理流程:
1.如果bin log无记录,Redo Log无记录,回滚事务
2.如果bin log无记录,Redo Log有记录,状态为Prepare,回滚事务
3.如果bin log有记录,Redo Log状态为Prepare,提交事务
4.如果bin log有记录,Redo Log状态为Commit,事务已完成,不需要恢复
以上就是本章的全部内容了。
上一篇:mysql第二话 - mysql架构和执行流程 下一篇:mysql第四话 - mysql bin log的开启及使用
三更灯火五更鸡,正是男儿读书时。黑发不知勤学早,白首方悔读书迟