InnoDB存储引擎
内存缓存结构(BufferPool)
如果每次获取数据都去磁盘获取,这样效率明显比较慢。所以innoDB为了性能,采用了内存缓存的机制,在内存中缓存一定的数据。我们称之为BufferPool。
BufferPool默认大小为128M。
设置大小,单位:字节
SET GLOBAL innodb_buffer_pool_size=402653184
内存与磁盘数据交互机制
页加载机制
取数据的流程
查询语句
select * from table where id>2
如果最终返回的数据有id=3、4、5 总共三条数据
1.去bufferpool 中查看3、4、5所在的page是否存在
2.存在就直接返回
3.不存在,根据3、4、5的数据所在的page页,去磁盘加载,加载完后保存到内存
4.下一次查询id=4的数据内存中已经存在,直接返回
预读机制
预读是一种我就算没读也能够提前加载数据到内存的机制。其中用线性预读和随机预读两种机制:
1 线性预读
2.随机预读
数据同步机制
当我们将数据存放到内存,这时候我们的系统中将存在两分数据,一份在内存,一份在磁盘,这时候如果我们对数据进行操作,可能会导致两边数据不同步,那我们就需要对两边数据进行同步处理。
脏页
对于InnoDB,每次更改数据,会先判断内存是否存在,如果存在,会直接修改内存中的数据,且是以page维度去修改。那么这个page与磁盘中的数据不一致了,我们称其为脏页。
对于没用修改的的页称为干净页,如果分配的page没有数据,则称为空页。
Flush链表
对于脏页,我们肯定是要去同步到磁盘的,而这个动作我们称为刷脏,我们应该去哪里寻找脏页呢?
在InnoDB的bufferpool中,会将脏页信息单独放在一个链表中,刷脏的时候只需要从这个链表中寻找即可,而这个链表被称为Flush链表。
异步刷脏
出于对性能的考虑,刷脏的方式是异步执行的。具体的线程数由配置innodb_page_cleaners控制
SELECT @@innodb_page_cleaners; --默认是4 但是不能超过buffer-pool的实例数
SELECT @@innodb_buffer_pool_instances;
刷脏的模式分为3种:
双写(doubleWrite)
page页会异步刷新到磁盘,但是如果在写得过程中发生意外退出导致写入失败怎么办?这种情况肯定是不被允许的,所以MySQL提供了一个doubleWrite(双写)机制。
1.当脏页写入到bufferpool中时,同时会被copy到Doublewrite缓冲区中。
2.Doublewrite缓冲区中的数据会先到另一处磁盘文件中,这是一个顺序IO,写入效率非常高。
3.将数据写入到真正的磁盘中。
4.如果写入过程发生意外,可以从另一处磁盘中读取恢复到一致的状态。
Doublewrite为了保证数据的安全性和可靠性,会产生一定的性能损失,这是一种权衡下的结果。
RedoLog
由于刷脏的过程是异步的,如果在同步到磁盘之前就宕机了,数据就丢失了,那么InnoDB怎么去保证数据的一致性与持久性呢?
RedoLog格式
RedoLog file存储
RedoLog写入方式
RedoLog Buffer
redolog是为了保证数据一致性跟持久性的同时,性能得到保证,出于性能考虑,又在内存中申请了一个LogBuffer区间,这个内存区间用来缓存我们的RedoLog, RedoLog不马上写到磁盘,而是先写到 LogBuffer,然后再从Log Buffer同步到磁盘。
这个buff同步时机:
1.buffer空间不足时
buffer是有大小限制的,可以通过innodb_log_buffer_size来进行设置,当内存不足时,会将buffer数据刷新到磁盘
2.事务提交时
3.后台异步线程刷新
后台有一个线程,大约每秒都会刷新一次log buffer中的redo日志到磁盘
4.正常关闭服务器时
....
Redolog Buffer跟磁盘的同步
我们知道了,LogBuffer什么时候刷新到磁盘了,那么只要触发刷新到磁盘,就能百分比保证数据不丢失么?如果不丢失,那么性能是不是又很 慢。
SELECT @@innodb_flush_log_at_trx_commit; 默认设置为1
顺便一提 MySQL三大日志其他两个
Undo Log( 回滚日志)
Undo log ( 撤销日志,或者回滚日志)记录了事务发生之前的数据状 态,分为insert undo log 或者 update undo log ,如果事务需要回滚或者我们修改数据的时候出现异常,我们可以通过undolog 来实现回滚操作(保证原子性)。 redo log 和 undo log 与事务都密切相关,统称为事务日志
Bin log
Bin log 是MySQL Server 层维护的二进制日志,与Innodb 存 储引擎是完全不同。 其实就是主要用于MySQL数据更新或者潜在更新的SQL语句,并且 “以事务的形式保存在磁盘”,并且还是逻辑日志(SQL)。
作用:
1.主从复制:MySQL 主从复制,在Master 端开启Binlog, Master 把它的二进制的日文件传递给slaves并且回放,来达到数据一致 性。
2.数据备份:
3.增量备份:
Binlog是默认关闭的
Binlog开启之后就需要两阶段提交
2个log,一个redolog,一个binlog,一个是InnoDB存储引擎的,一个是server端的日志文件;这2个日志不是1个地方操作的,那么就不是原子性的;就会产生数据一致性问题;要么恢复的数据有问题,要么复制备份的数据会有问题。
为什么要二级阶段提交?
为了保证redolog和binlog 数据的安全一致性,只有这个两个日志文件逻辑高度一致了,你才能放心使用,数据能够帮你做奔溃恢复以及主从同步等等的问题,redo能够帮你讲数据的状态回到崩 溃之前,使用了Binlog 实现数据备份、恢复、以及主从同步嘛,二两阶段机制可以保证这两个日志的逻辑是高度一致的,没有错误, 没有冲突。