公众号原文链接
RocketMQ思维导图,不看会后悔哟
Mysql思维导图分享
上面思维导图可在gongzhonghao回复:扣扣号,获取联系方式后找我免费获得可编辑版本。 后面会继续分享其他思维导图,包括Redis、JVM、并发编程、RocketMQ、RabbtiMQ、Kafka、spring、Zookeeper、Dubbo等等 |
思维导图
mysql存储补充(图片看不清)
Page结构
o页头
记录页面的控制信息,共56字节。包括页面的左右兄弟页指针、页面空间使用情况等
o虚记录
最大虚记录:比页中最大主键还大
最小虚记录:比页中最小主键还小
所以能知道一个页的主键 范围
o记录堆
行记录存储区。分为有效记录和已删除记录
o自由空间链表
记录堆中删除数据后,地址用一个链表记录。这个链表就是自由空间链表
o未分配空间
页面还未使用的存储空间
oslot区
查找行记录的,是一个连续空间,相当于跳表。参考后面的页内查询
o页尾
页面的最后一部分,共占8字节。主要存储页面的校验信息
脏页
o定义
内存数据页和磁盘数据页不一致时,那么称这个内存数据页为脏页
o产生原因
数据插入时,为了效率会优先插入顺序写的redo log日志中,后面才会做随机写的操作来写入磁盘
redo log还未同步到磁盘时,就会产生脏页
注:redo log日志也是写到磁盘,因为是顺序读写所以快
o影响
在缓存淘汰时,如果淘汰的是脏页,则需要将脏页的数据刷到磁盘中,这个过程较慢
redo log满了之后刷盘比较慢
页内记录维护
o顺序保证
物理有序
物理地址是连续的,方便查找(如二分查找),但是插入时,如果不是顺序插入,则会不停移动数据
逻辑有序
用链表连接,没有数据移动,插入很快,但是查找很慢,不能进行偏移查找,只能遍历
物理有序太多限制,选择逻辑有序,现在需要优化查询
o插入策略
可以先自由空间链表找位置插入
也可以从未分配空间插入
在加载page到内存中时,如果page中删到只余下一条记录,也会整个page加载到内存中,造成内存空洞所以插入时最好先插入到已删除的位置里
o页内查询
遍历
二分查找
二分查找slot,然后再遍历子链表【类似跳表结构】
内存管理
o预分配一块内存
内存不能现用现分配,分配内存耗时间
o数据加载单位:页
一般数据前后挨着的数据也是大概率也要访问的,所以一次加载一页,以减少磁盘IO提高性能
o内外存交换
内存没有磁盘大,内存满了需要移除一些数据,修改数据时要同步到磁盘里
o名词解释
buffer pool
预分配的内存池
Page
buffer pool的最小单位
free list
空闲页组成的链表
flush list
脏页链表
page hash 表
维护内存page和文件page的映射关系
LRU
内存淘汰算法,最近最少使用原则
o内存页管理
页面映射
页面数据管理
空闲页
o没有数据的页,可以专门用一个链表记录哪些是空闲页
数据页
o正常的数据页,也叫干净页
脏页
o页内数据与磁盘内存不一致
上面几种页都可以用一个专门的数据结构来记录管理,比如链表
o数据淘汰
内存页都被使用
需要加载新数据
oLRU
页面加载
磁盘数据加载到内存:从磁盘加载到内存时,先尝试放进一个free page里,然后这个free page写了数据后链接到LRU old头,然后把映射关系写入到page hash中
没有空闲页后查找内存顺序
ofree list > LRU淘汰 > LRU flush【从LRU尾巴开始找脏页,将其刷盘淘汰直接放到free list】
页面淘汰
LRU尾部淘汰
Flush LRU淘汰
位置移动
old到new
oinnodb_old_blocks_time:old区存活时间大于此值时,有机会进入new区
new到old
LRU_new的操作
该操作是某个节点往表头移动
表头变动要加锁,需要减少移动次数
移动时机:当前淘汰页次数 - 上次移动header时的淘汰次数 > 1/4的LRU_new
o缓冲池
存在位置
减少磁盘IO
大小设置
当分配给buffer pool的总内存小于1G时,则最多只能有一个buffer pool实例
当分配内存大于1G时,则可以自定义设置成多个buffer pool实例,推荐设置总大小为总内存的50%-60%
innodb_buffer_pool_size = 8589934592 // 分配8G内存
innodb_buffer_pool_instances = 4 // 设置4个buffer pool实例
预读
当顺序访问的数据页超过了innodb_read_ahead_threshold的阈值时,就会触发预读,即把下一个相邻区中的所有数据页都加载到内存中
当检测到已经在buffer pool 中有连续数据达到innodb_random_read_ahead的设置值后,就会去把剩余的数据页也加载到buffer pool里
预读失效:一次读取两数据页时,只有访问了一个数据页,另一个数据页没有人访问,这个没人访问的内存页可能会把历史的数据淘汰掉
缓冲池污染
SQL中执行了太多的查询,把之前的数据都淘汰了,查其他数据就会变得很慢
缓冲空间管理
使用LRU淘汰内存
oleast recently used
冷热数据分离
o将数据分成两个LRU 链表,一部分为热数据区域5/8,一部分为冷数据区域3/8。由innodb_old_blocks_pct参数决定 ,默认37,即冷数据区占37%
o当数据页第一次被加载到缓冲池中的时候,先将其放到冷数据区域的链表头部,1s后(由 innodb_old_blocks_time 参数控制) 该缓存页被访问了再将其移至热数据区域的链表头部
o热数据区的后 3/4 部分被访问后才将其移动到链表头部去,对于前 1/4 部分的缓存页被访问了不会进行移动