随机i/o:
InnoDB中页被划分为了七个部分:
文件头
文件尾
空闲空间,指的是页中还没有使用的空间
用户记录,存储行记录的内容,叶子节点就是真正的数据,用户记录中的数据按照指定的行格式排列,相互之间形成单链表
最大最小记录,是两个虚拟的行记录,mysql会自动给每个页里增加最大和最小记录
页头,记录了很多页的状态信息,例如槽的数量、记录的数量、第一条记录的地址等
页目录,大小不定,存储用户记录的相对位置
文件头和文件尾:
页目录:
从页的角度看b+树的检索:
普通索引和唯一索引在效率上的差距:
行格式可分为四种:
compact行格式:
行溢出问题:
dynamic和compressed行格式:
redundant :
区(Extent)
段(Segment):
碎片区:
区的分类:
表空间
MySQL 的大表查询为什么不会爆内存
在应用系统中,为了加速数据访问,可以把高频的数据放在缓存中。例如:Redis、MongoDB里,来减轻数据库的压力,在操作系统中,为了减少磁盘IO,引入了缓冲池(buffer pool)机制,MySQL作为一个存储系统,为提高性能,减少磁盘IO,同样具有缓冲池机制
Buffer Pool也就是【缓冲池,简称BP】,是一块内存区域,用于缓存表数据与索引数据,把磁盘上的数据加载到缓冲池,避免每次访问都进行磁盘IO,起到加速访问的作用,Buffer Pool默认大小 128M,用于缓存数据页(16KB)
所有数据页的读写操作都需要通过buffer pool进行,
当我们在写入数据的时候,先更新Buffer Pool中的数据页,然后将更新操作顺序写Redo log,写操作的事务持久性由redo log 落盘保证,buffer pool只是为了提高读写效率。
Buffer Pool里有三个链表,LRU链表,free链表,flush链表,InnoDB通过这三个链表的使用来控制数据页的更新与淘汰的
控制块
中,并且将控制块从Free链表中脱离加入到LRU链表中buffer pool的工作流程,大致可以分为三步:
MySQL对LRU算法的改进
LRU 算法存在的问题:预读失效和Buffer Pool 污染
预读失效
预读也就是为了减少磁盘IO,innoDB会把数据从磁盘读取到内存中使用,磁盘数据读取到内存,并不是按需读取,而是按页读取,一次至少读一页数据(16K),如果未来要读取的数据就在页中,直接读取内存即可,不需要磁盘IO,提高效率
预读失效,也就是那些被提前加载进来的数据页并一直没有被访问,预读的数据会被放到 LRU 链表头部,而当 Buffer Pool空间不够的时候,需要把末尾的页淘汰掉。如果这些预读的数据一直没有被使用,就会被挤到链表的尾部,进而被淘汰,那缓存的命中率就会大大降低,相当于预读是白费功夫
但是并不能因为预读失效,而将预读机制去掉,所以需要提高缓存的命中率。
innodb_old_blocks_pc
参数来设置)Buffer Pool 污染
脏页的刷盘时机
innodb缓冲池
change buffer就是在非唯一普通索引页不在buffer pool中时,对页进行了写操作的情况下,先将记录变更缓冲,等未来数据被读取时,再将 change buffer 中的操作merge到原数据页的技术。
在MySQL5.5之前,叫插入缓冲(insert buffer),只针对insert做了优化;现在对delete和update也有效,叫做写缓冲(change buffer)。
原理
change buffer为什么针对非唯一普通索引页
MySQL 是如何保证数据不丢失的
只要redolog 和 binlog 保证持久化磁盘就能确保MySQL异常重启后回复数据
在恢复数据时,redolog 状态为commit 则说明 binlog 也成功,直接恢复数据;如果redolog 是prepare(准备),则需要查询对应的 binlog事务是否成功,决定是回滚还是执行。
redlog:
binlog
binlog和redolog的区别:
redolog是在InnoDB存储引擎层记录的,而binlog是mysql数据库服务器层记录的
两种日志记录的内容形式不同,MySQL的binlog是逻辑日志,而InnoDB存储引擎层面的重做日志是物理日志。
两种日志与记录写入磁盘的时间点不同,二进制日志只在事物提交完成后进行一次写入,而redolog的重做日志在事物的进行过程中不断地被写入。
binlog不是循环使用,在写满或者重启之后,会生成新的binlog文件,但是redolog是循环使用的。
如何理解 MySQL 的边读边发
mysql_use_result的使用