mysql的存储引擎之InnoDB
一.写入原理Buffer pool
mysql的最终写入地点还是物理储存,也就是我们所说的磁盘,众所周知,内存的写入和查询速度要远大于磁盘的读写速度,
所以基于这个特点,innoDB在内存中提供了一个缓冲区:Buffer Pool
我们知道InnoDB是支持事务回滚的,那么我们在使用回滚的时候,怎么找到原来的数据呢?
在写入数据的时候,InnoDB就会把数据原来的值写入在:Undo Log中,这就是一个日志,用于记录更改前的旧值。
步骤:也就是执行器会将要写入的位置之前的先记录到Undo Log中,然后把要刷入磁盘的大量信息和从磁盘查询出来的数据都会存在内存中,由于内存速度快,
大量的增删改信息都会先在Buffer Pool中,然后慢慢的刷入磁盘中
二.断电后MySQL的数据保护机制redo log
细节的小伙伴一下就发现了一个漏洞,那就是我们的mysql在断电后,还在Buffer Pool中的未写入的数据怎么办?
所以InnoDB专门设置了一个redo log buffer来存储增删改数据库的信息,光是在内存中新建一个buffer是不够的,这些信息也会被写入到磁盘中,
在磁盘中有一个叫redo log的文件专门存储redo log buffer中的信息,
在mysql断电以后,重启后内存中的数据肯定会被清除,但是磁盘中的依旧存在,所以redo log会重构信息,也就是重构那些由于断电后没有刷入磁盘的信息,
但是真正写入磁盘文件.ibd中的还是redo log block,redo log的文件也会重构在redo log block(他自己的位置在内存中,从磁盘重构到内存中) 中,
那么什么时候redo log block会将信息刷入磁盘文件呢?
(1)如果直接重构时就填满了,redo log block就会直接刷入磁盘文件,(redo log buffer的大小,默认是16MB,其实已经够大了,因为一个redo log block才512字节而已,每一个redo log也不过几个字节到几十个字节罢了。)
(2)如果在一瞬间写入大量sql,redo log buffer的存储超过了一半,也就是有8MB在redo log 的缓存中,就会刷入到磁盘中去
(3)每次当事务提交后,redo log block也必须将信息刷入到磁盘中
三.MySQL的BinLog
上面的两个机制,是对数据写入磁盘的一些异常所设立的机制,这些机制都只会保证你在sql语句的写法正确后,整个数据库才会稳定,但是对于程序员在sql语句层面都写错了后就没有办法了,
如果sql都写错了,那么他也会正常的写入数据库,对于整个数据库写入磁盘的数据查错并不乐观,
所以MYsql为我们提供了另外一个日志,BinLog:它的作用就是变更历史数据查询,数据库备份和恢复,主从复制等功能;
值得注意的是,BinLog并不属于InnoDB特有,而它是属于的MySQL server,也就是mysql自带的日志功能;
它的写入操作:在redo log写入的同时,也会进入BinLog的刷盘操作;
当BinLog刷盘完成后,就会告诉redo log已经刷入的信息,redo log就会打上commit的标记;
四.MySQL的独立表空间文件.ibd
关于MySQL的数据存储,我们都知道,一个MySQL的数据库是由多个表构成的,每一个数据表都有一个属于自己的表结构,
比如表结构中会记录数据的存储引擎,InnoDB或者MYISM等等信息是存储在.frm文件中的,
.ibd文件主要存储的数据,它记录的数据存储结构,
数据的最小存储的单位被称之为页,它的大小有16kb,一般的数据库在创建的时候会先申请6个页,前四个页都是装的表配置,只有后两页是空闲页,
只有空闲页可以用来装数据,每一个装数据的页分为页头和页尾,即File Header,File Trailer,在页头和页尾之间就是装的数据(即一条一条的记录),
当一页装满了以后,就会申请下一页;
由64个页构成一个区(第一个区的前四页最特殊,存储的表配置,后面的区都只有前两页是存储的表配置);
由256个区构成一个组;
除此之外,还有一个标记“区”和零散 “页”(零散页指的是不构成区的那些页,即没有64页) 的逻辑 “段”
.ibd表结构的完整图概念: