BufferPool
BufferPool里面是数组默认128M,执行sql,会把磁盘里面的页放在BufferPool里面。
free链表,存的是BuferPool里面哪些位置暂时是空的
基点里面存1、有多少个控制块 2、第一个控制块位置
当执行update语句时,要先在BufferPool里面找到那个页,Flush链表用于记录那些页被修改了,找到了再将该页写回磁盘。
LRU链表记录的是刚刚被使用的页
当BufferPool放满了之后,会使用最近使用最少算法LRU淘汰,最近被使用的页要加在LRU链表的头部,则淘汰的就是尾部的页
全表扫描导致的换血:
当BufferPool里面的存储一些热点数据和剩余部分空间,但你再执行sql时,剩余空间不够存储从磁盘里读取的页,这是热点数据就会被冲掉,那你下次再读热点数据时,就需要取磁盘里面去读,再写入BuuferPool缓存中,影响了执行效率。
解决方式:分区
热数据区和冷数据区
什么时候怎样冷数据区能到热数据区?
第二次访问的时间 - 第一次访问的时间 > 1s 的时候把冷数据放到热数据里面。
为什么不应该时小于1s吗?
为了防止你查询一张表的时候,会不断的执行sql语句,不停连续的访问该表所对应的控制块,这种时间间隔肯定小于1s,但它不是热数据,不能加到热数据里面区。
当访问的是热数据的后面的1/4,这时才把它移到前面去,本来就靠前的被访问了没有很大的必要再往前移
update
1、更新Buffer Pool里的页数据
2、生成一个redolog对象
bin log
undo log
3、持久化redolog对象
4、后台线程也数据的持久化
执行完update后再事务提交后,才会持久化redolog对象(即事务提交的时候回去持久化redolog对象),但后台页数据的持久化是线程定时任务去执行。
文件调大缺点:mysql重启的时候用redolog,时间会变久
为什么执行update要生成一下两个文件?
bin log ------>Mysql Server(会支持很多存储引擎)-----> 主从同步与存储引擎没关系的
redo log-----> Innodb引擎----> 记录的是update修改的那一页,这一页哪一个位置的数据----> 恢复数据
bin log 主从复制传给从服务器,但为什么不是redo log传给从服务器?
因为如果你没用Innodb引擎,照样可以主从复制
重启mysql时redo log自动恢复数据
undo log :回滚,记录的是update(update),insert(delete id),delete(insert id)的反向记录
双写缓冲区
Innodb最小的存储单位就是一页(16kb),操作系统里的一页(4kb),如果你在写一部分的时候操作系统挂了,怎么办?
Innodb在磁盘里面在创建双写缓冲区,让数据先写入双写缓冲区(双写缓冲区写到一半失败了,表空间数据没有错误)再写入表空间(这个过程再出现错误,但是双写缓冲区里面有完整的数据了,再写入即可),以免数据丢失
一个表有两千万数据,三层,按照一页=16kb,一页16条,假设主键ID为bigint类型,长度为8字节,而指针大小在InnoDB源码中设置为6字节,这样一共14字节.
单个叶子节点(页)中的记录数=16K/1K=16。(这里假设一行记录的数据大小为1k,实际上现在很多互联网业务数据记录大小通常就是1K左右)。
当B+树高度为3,可以存放的数据达到2千多万(1170* 1170 *16)每页可以存储16KB,大概可以存放1170个节点和下个磁盘的存放位置。