欢迎关注公众号(通过文章导读关注:【11来了】),及时收到 AI 前沿项目工具及新技术的推送!
在我后台回复 「资料」 可领取
编程高频电子书
!
在我后台回复「面试」可领取硬核面试笔记
!文章导读地址:点击查看文章导读!
感谢你的关注!
bin log、redo log、undo log 作用:
-
bin log:bin log 叫做归档日志,主要记录了做了什么操作,比如更新一行数据,bin log 就记录了对哪一行数据做更改,更新前的值是什么,更新为了什么值。bin log 日志是用于恢复磁盘中的数据
其中 redo 日志和 undo 日志是 InnoDB 引擎特有的,而 bin log 是属于 Server 层的,与存储引擎无关
-
redo log:redo log 叫做重做日志,用于恢复 BufferPool 中的数据
-
undo log:用于进行数据的回滚
redo log 如何恢复 BufferPool 中的数据呢?
如果 MySQL 在 BufferPool 中修改过数据之后宕机了,此时 BufferPool 中的数据还没有来得及刷到磁盘中,而 BufferPool 是在内存中的,因此里边的数据会在宕机之后会全部丢失
而 redo log 就是用于恢复 BufferPool 中的数据,在 BufferPool 中修改数据后,会将 redo log 写入到 redo buffer 中,此时 redo log 还没有刷到磁盘中去,如果 MySQL 宕机的话,redo log 也会丢失,而当提交事务之后,会将 redo log 刷到磁盘中去,此时 MySQL 宕机的话,也可以根据磁盘中的 redo log 将这一次的更新操作给恢复到 BufferPool 中
redo log 的刷盘策略:
redo log 的刷盘策略通过 innodb_flush_log_at_trx_commit
参数来配置
innodb_flush_log_at_trx_commit
值为 0 时:提交事务时,不会把 redo buffer 中的数据刷入到磁盘中(一般不使用)innodb_flush_log_at_trx_commit
值为 1 时:提交事务时,必须把 redo buffer 中的数据刷入到磁盘中(建议使用)innodb_flush_log_at_trx_commit
值为 2 时:提交事务时,把 redo buffer 中的数据写入到 os cache 中,而不是直接写入磁盘,过一会再写入磁盘,此时如果机器宕机的话,os cache 中的数据也会丢失(一般不使用)
bin log 的刷盘策略:
在准备提交事务时,会写入 bin log 到磁盘中去,bin log 也有不同的刷盘策略,通过 sync_binlog
参数控制
sync_binlog
值为 0:默认情况,在bin log 写入磁盘的时候,不直接写入磁盘文件,而是先写入到 os cache 中,隔一段时间后再写入到磁盘中去sync_binlog
值为 1:提交事务时,会强制将 bin log 写入到磁盘中去
MySQL 的预读机制:
当从磁盘上加载一个数据页时,MySQL 可能会连带着把这个数据页相邻的其他数据页也加载到缓存里去。
触发 MySQL 的预读机制的场景?
-
线性预读:参数
innodb_read_ahead_threshold
默认值是 56,表示如果顺序的访问了一个区里的多个数据页,访问的数据页的数量超过了这个阈值,就会触发预读机制,把下一个相邻区中的所有数据页都加载到缓存里去查看默认值:
show variables like 'innodb_read_ahead_threshold'
-
随机预读:如果 Buffer Pool 里缓存了一个区里的 13 个连续的数据页,而且这些数据页都是比较频繁会被访问的,此时就会直接触发预读机制,把这个区里的其他的数据页都加载到缓存里去。
性能不稳定,在 5.5 中已经被废弃,默认是 OFF
show variables like 'innodb_random_read_ahead'
LRU 优化—冷热分离
MySQL 通过使用 LRU 来判断哪些缓存页经常访问,哪些缓存页不常访问,来判断当 BufferPool 缓存被占满之后去淘汰哪些缓存页。
在 MySQL 的 LRU 链表中,采取了 冷热数据分离的思想
,LRU 链表被拆为了两部分,一部分是热数据,一部分是冷数据,冷数据默认占比 37%,由 innodb_old_blocks_pct
参数控制
查看参数:
show variables like 'innodb_old_blocks_pct'
,默认是37
原理:数据页第一次被加载到缓存页之后,这个缓存页被放在 LRU 链表的冷数据区域的头部,在 1s(可配置) 之后,如果这个缓存页再次配访问,该缓存页才会被移动到热数据区域的头部。
查看参数:
show variables like 'innodb_old_blocks_time'
,默认是 1000 毫秒(配置多长时间之后访问该缓存页,才将该缓存页加入热数据区域头部)
为什么 LRU 要进行冷热分离?
如果不这样优化,在 LRU 只使用一个链表,那么在预读机制中多加载的一些缓存页,可能就在刚加载进缓存时使用一下,之后就不再使用了,如果被放在 LRU 链表头部了,会将频繁访问的缓存页挤在 LRU 链表尾部,最后被淘汰。预读机制和全表扫描加载进来的一大堆缓存页,此时都在冷数据区域里,跟热数据区域里的频繁访问的缓存页时没有关系的。
LRU 中热数据区域访问的一些优化:
一般在热数据区域头部的缓存页可能是经常被访问的,所以频繁移动性能不太好,所以 MySQL 对于热数据区域的访问优化了一下,只有在热数据区域的后 3/4 部分的缓存页被访问了,才会被移动到链表头部去(这样就
不会出现链表头部数据频繁交替访问,导致频繁移动链表头部数据)。