【MySQL性能优化】- 一文轻松学会BufferPool缓存机制

BufferPool缓存机制

😄生命不息,写作不止
🔥 继续踏上学习之路,学之分享笔记
👊 总有一天我也能像各位大佬一样
🏆 博客首页   @怒放吧德德  To记录领地
🌝分享学习心得,欢迎指正,大家一起学习成长!

转发请携带作者信息 @怒放吧德德 @一个有梦有戏的人

在这里插入图片描述


转发请携带作者信息 @怒放吧德德 @一个有梦有戏的人

前言

上一篇文章《MySQL结构与SQL执行过程》介绍了MySQL的结构以及执行的过程,接下来就来介绍其在InnoDB中BufferPool的缓存机制。本文主要介绍了MySQL中InnoDB存储引擎的Buffer Pool缓存机制及其与日志文件的协同工作原理。Buffer Pool是InnoDB的核心组件,通过缓存数据和索引页,减少磁盘I/O操作,提升数据库性能。文章还详细介绍了三种日志文件(Undo Log、Redo Log和Bin Log)的作用、区别以及它们在事务处理中的协同工作流程。

BufferPool概念

MySQL的Buffer Pool(缓冲池)是InnoDB存储引擎的核心组件,负责在内存中缓存数据和索引,减少磁盘I/O操作,大幅提升数据库性能。BufferPool 包含了磁盘中的部分页数据,是作为访问数据库的一个缓冲池,作为内存缓存区,存储频繁访问的数据页(Data Page)和索引页(Index Page),并且所有读写操作优先在Buffer Pool中进行,避免直接访问磁盘。磁盘I/O速度比内存慢几个数量级,Buffer Pool通过减少磁盘访问,成为MySQL性能优化的关键。

当我们从数据库读取一条数据时,MySQL 会首先在Buffer Pool 中查找这个数据,如果找到了,那么就直接从Buffer Pool中读取数据。如果没有找到,MySQL 就会从磁盘中读取数据,并将数据存储到Buffer Pool 中,这样下次查询同样的数据时,就可以直接从缓存中获取,而不需要再次从磁盘中读取。

BufferPool工作原理

BufferPool 的最小单位是 Page,这是数据库中的一个页面,大小可能是 4KB 或 8KB。(bufferpool 一般设置机器内存的 60%左右)

数据读取流程

当 MySQL 读取数据的时候,首先 InnoDB 会先检查 BufferPool 是否存在对应的页。如果存在的话,就会直接返回内存中的数据;如果不存在,则会先从磁盘中读取页到 BufferPool 在返回数据。

数据写入流程

当 MySQL 写/修改数据的时候,首先会更新 BufferPool 的页,此时页变为脏页。脏页会由后台线程(如Checkpoint机制)异步刷回磁盘,确保数据最终持久化。

缓存淘汰策略

使用改进的LRU算法管理内存,将LRU链表分为Young区(热数据)和Old区(冷数据)。新加载的页先插入Old区头部,若在指定时间(innodb_old_blocks_time)后被再次访问,才移动到Young区。这样做的优势是避免全表扫描等短期大量操作污染热数据。

三种日志文件

在数据库系统中,undo log、redo log 和 bin log 是三种关键的日志机制,分别承担不同角色,共同保障事务的 ACID 特性(原子性、一致性、隔离性、持久性)。

Undo Log(回滚日志)

UndoLog 逻辑日志,主要用于事务的回滚和MVCC。当用户执行一个事务时,如果事务需要回滚,undo log会记录修改前的数据,这样就可以恢复到之前的状态。另外,MVCC需要读旧版本的数据,undo log也能提供支持。比如,InnoDB引擎用undo log来实现事务的回滚和一致性读。

  • 存储位置:InnoDB 引擎层维护,存储在 表空间 或独立的 undo 文件中。
  • 日志类型:逻辑日志(记录反向操作,如 <font style="color:rgb(64, 64, 64);">INSERT</font> 对应 <font style="color:rgb(64, 64, 64);">DELETE</font>)。
  • 生命周期:事务结束后,若没有其他事务依赖其旧版本数据,undo log 会被清理。

事务更新<font style="color:rgb(64, 64, 64);"> UPDATE t SET name='Bob' WHERE id=1</font>,undo log 会记录 name=‘Alice’(旧值),以便回滚或供其他事务读取历史版本。

Redo Log(重做日志)

RedoLog 物理日志,主要是为了崩溃恢复。在事务提交的时候,数据页可能还没写入磁盘,这时候如果系统崩溃,redo log可以重放这些操作,确保持久性。redo log是物理日志,记录的是页的修改,顺序写入,所以写入速度比较快。通常有固定大小,循环覆盖使用。事务提交时先写入 redo log(Write-Ahead Logging, WAL 机制),再异步刷脏页到磁盘。

*如果事务提交成功,但是bufferpool还没来得及写入磁盘,此时系统宕机了,这时候就可以使用redo日志的数据来恢复bufferpool的缓存数据。

事务提交后,即使数据页未刷盘,只要 redo log 落盘,重启后可通过 redo log 重放恢复数据。

Bin Log(二进制日志)

二进制日志,属于MySQL Server层的,主要用来主从复制和数据恢复。它记录的是逻辑操作,比如执行的SQL语句。bin log有三种模式,statement记录SQL,row记录行变化,mixed混合两种。主从同步的时候,从库通过bin log来重放操作,保持数据一致。事务提交后顺序写入 bin log,通过 <font style="color:rgb(64, 64, 64);">sync_binlog</font> 参数控制刷盘策略。

主库执行 DELETE FROM t WHERE id=1,bin log 记录该操作(或具体行变化),从库读取后重放。

三者的区别

undo log和redo log是InnoDB引擎层的,而bin log是MySQL Server层的。undo log用于回滚和MVCC,redo log保证持久性和崩溃恢复,bin log用于复制和恢复。事务提交时,redo log先写,bin log后写,两阶段提交保证一致性。

特性Undo LogRedo LogBin Log
层级InnoDB 引擎层InnoDB 引擎层MySQL Server 层
日志类型逻辑日志(反向操作)物理日志(页修改)逻辑日志(SQL/行变更)
目的回滚事务、MVCC崩溃恢复、持久性主从复制、数据恢复
生命周期短(事务结束后清理)长(覆盖循环写入)长(可配置过期时间)

以更新为例,简单由以下三个步骤来实现:

  1. 事务执行 <font style="color:rgb(64, 64, 64);">UPDATE</font>
    • 生成 undo log(记录旧值)。
    • 修改内存数据页,生成 redo log(记录新值)。
  2. 事务提交:
    • redo log 刷盘(<font style="color:rgb(64, 64, 64);">prepare</font> 状态)。
    • bin log 刷盘。
    • redo log 标记为 <font style="color:rgb(64, 64, 64);">commit</font> 状态(两阶段提交,保证一致性)。
  3. 后台线程异步将脏页刷盘,清理 undo log。

案例分析

接下来我们通过一个案例来分析整个流程是怎么流转的,我们通过一句更新语句来讲解案例。

update user set name = 'lydabc' wherer id = 1

首先先看一下以下的图,这是 MySQL 的执行流程。
在这里插入图片描述

我们主要看下部分,我们知道每次增删改查首先到达的就是 BufferPool 查询,没有找到的情况才去磁盘文件中获取。当执行更新语句的时候,MySQL 并不是直接将数据修改到磁盘文件中的。执行流程如下:

  1. 首先会先加载缓存数据,将id=1的所在的磁盘文件中的整数据加载到缓存池中。(这里需要注意加载的数据是整页整页加载的,此时 bufferpool 的值 name=lyd)
  2. InnoDB 引擎会把更新前的旧值写入 Undo Log 文件中(此时里面的值是name=lydabc),这是为了方便数据回滚。
  3. 接着就是执行器来更新内存数据(此时 bufferpool 的值 name=lydabc),但是磁盘文件目前还不是。
  4. 写入 Redo 日志,这里的写入并不是一条一条,而是批量的写入。
  5. 在准备提交事务的时候,redo log buffer 会真正写入磁盘(Redo Log 文件)。redo log 文件是 innoDB 持有的,如果事务提交成功,但是bufferpool还没来得及写入磁盘,此时系统宕机了,这时候就可以使用redo日志的数据来恢复bufferpool 的缓存数据。(此时 redo log 的值 name=lydabc)
  6. 准备提交事务 binlog 写入磁盘。这里写入到 binlog 文件,这是MySQL Server 层维护,独立于存储引擎(如 mysql-bin.000001)。(此时 bin log 的值 name=lydabc),bin日志主要是用来恢复数据库磁盘里的数据。
  7. 当 binlog 写完之后,会写入commit标记到redo日志文件中,提交事务完成(该标记是为了确保事务提交之后,redo日志与bin日志文件是一致的。)
  8. 当事务提交完成之后,磁盘文件的数据并没有直接更新,更新的时机是不固定的,是通过异步刷回磁盘,以page为单位,通过 IO 线程来随机写入磁盘,这步操作完毕之后,磁盘的name=lyd就会改成lydabc。

经过这些复杂流程,数据才算真正更新完毕。

总结

文章详细介绍了MySQL中Buffer Pool的缓存机制及其与三种日志文件(Undo Log、Redo Log和Bin Log)的协同工作流程。Buffer Pool通过缓存数据页和索引页减少磁盘I/O,提升性能;而三种日志文件分别负责事务的回滚、崩溃恢复和主从复制等功能。通过这些机制,MySQL能够高效地处理事务并保证数据的一致性和持久性。


转发请携带作者信息 @怒放吧德德 @一个有梦有戏的人
持续创作很不容易,作者将以尽可能的详细把所学知识分享各位开发者,一起进步一起学习。转载请携带链接,转载到微信公众号请勿选择原创,谢谢!
👍创作不易,如有错误请指正,感谢观看!记得点赞哦!👍
谢谢支持!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

一个有梦有戏的人

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值