欢迎关注公众号(通过文章导读关注:【11来了】),及时收到 AI 前沿项目工具及新技术的推送!
在我后台回复 「资料」 可领取
编程高频电子书
!
在我后台回复「面试」可领取硬核面试笔记
!文章导读地址:点击查看文章导读!
感谢你的关注!
BufferPool 底层设计
Buffer Pool 是 MySQL 中的一个很重要的内存结构,MySQL 的增删改查都是直接操作 BufferPool 的,一般设置 BufferPool 的大小为机器内存的 60% ,Buffer Pool 的大小在 /etc/my.cnf
中进行配置:
那么为什么要有 BufferPool 呢?
为什么不直接更新磁盘上的数据,而是需要设置一套复杂的机制来执行 SQL 呢?
因为针对数据库数据的读写其实是随机的读写,而对于日志文件的读写是顺序的读写,而顺序读写和随机读写速度差距在 2~3 个数量级,磁盘的顺序 IO 几乎可以和操作内存相媲美。
通过 BufferPool 可以保证每个更新请求都是更新内存 BufferPool,然后顺序写日志文件,同时可以保证各种异常情况下的数据一致性,正是通过这套配置,才能让我们的 MySQL 数据库在较高配置的机器上每秒可以抗下几千的读写请求
为什么说数据库数据的读写是随机 IO 呢?
因为数据库存储在磁盘中的数据是会被删除的,我们在写的时候就算一直顺序写,但是如果后边删除了中间的一些数据,那么在之后读就不能顺序读了,因为中间有一些数据已经不存在了
InnoDB 更新数据的 SQL 执行流程
1、如果需要更新的数据不在缓冲池中,就先去磁盘中加载数据页,把需要修改数据所在的数据页,缓存到 BufferPool,BufferPool 中缓存的其实就是一个个的数据页
2、修改记录前,写 undo 日志,记录更改前数据,如果事务执行失败,使用 undo 日志进行数据回滚
3、更新 Buffer Pool 中的数据,并且将 redo log 写到 redo buffer 中
4、提交事务时,会做两件事情:将 bin log 日志写入到磁盘,保存操作记录;将 redo buffer 中的 redo log 刷到磁盘中去,保存操作记录。
bin log 会按照一定的策略刷新到磁盘中去(通过 innodb_flush_log_at_trx_commit 参数来控制)
当 bin log 成功写入到磁盘后,接着就会完成事务的最终提交,之后会将更新的 bin log 的文件名称以及 bin log 日志在文件里的位置都写入到 redo log 中去,并且在 redo log 里写入一个 commit 标记
5、数据持久化,IO 线程不定期把 Buffer Pool 中的数据随机写入到磁盘,完成持久化
在 redo log 中写入 commit 标记的原因:
在 redo 日志中记录 commit 标记是为了保证事务提交之后,redo log与 bin log 数据一致
可以假设一种情况:当 bin log 刚写入磁盘之后,MySQL 宕机了,此时 redo log 还没有写入,那么此时就会出现数据的不一致现象
因此,当 bin log 写入磁盘成功后,在 redo log 中加上 commit 标记,这样即使在 bin log 写入磁盘后,MySQL 宕机了,此时 redo log 还没有加上 commit 标记,因此就认为此次事务执行失败