常见面试题-MySQL专栏(三)MVCC、BufferPool


typora-copy-images-to: imgs

了解 MVCC 吗?

答:

MVCC(Multi-Version Concurrency Control) 是用来保证 MySQL 的事务隔离性的,对一行数据的读和写两个操作默认是不会通过加锁互斥来保证隔离性,避免了频繁加锁互斥,而在串行化隔离级别为了保证较高的隔离性是通过将所有操作加锁互斥来实现的。

MySQL 在读已提交可重复读隔离级别下都实现了 MVCC 机制,ReadView 生成规则为:

  • 在读已提交隔离级别下,ReadView 生成的时机是每个 Select 生成一个 ReadView
  • 在可重复读隔离级别下,ReadView 生成的时机是每个事务生成一个 ReadView

MVCC 是基于 undolog版本链readview 实现的。
在这里插入图片描述

在每次更新或者删除数据时,都会将操作记录在 undo 日志中,每条 undo 日志 通过 roll_pointer 进行关联,构成了数据的版本链

ReadView 中包含以下参数:

  • m_ids:表示生成 ReadView 时,当前系统中活跃(未提交)的事务 id 数组
  • min_trx_id:表示生成 ReadView 时,当前系统中活跃的事务中最小的事务 id,也就是 m_ids 中的最小值
  • max_trx_id:表示生成 ReadView 时,已经创建的最大事务 id(事务创建时,事务 id 是自增的)
  • creator_trx_id:表示生成 ReadView 的事务的事务 id

那么在事务里的 sql 查询会和 ReadView 进行对比,来判断是否取该行的数据:

  1. 如果 row 的 trx_id < min_trx_id,表示这一行数据的事务 id 比 ReadView 中活跃事务的最小 id 还要小,表示这行数据是已提交事务生成的,因此该行数据可见
  2. 如果 row 的 trx_id > max_id,表示这一行数据是由将来启动的事务生成的,不可见(如果 row 的 trx_id 就是当前事务自己的 id,则可见)
  3. 如果 row 的 min_id <= trx_id <= max_id,则有两种情况:
    1. 如果 trx_id 在 ReadView 的活跃事务 id 数组(m_ids)中,则表明该事务还未提交,则该行数据不可见
    2. 如果不在,则表明该事务已经提交,可见

注意:

  • 执行 start transaction 之后,并不会立即生成事务 id,而是在该事务中,第一次修改 InnoDB 时才会为该事务生成事务 id
  • MVCC 机制就是通过 ReadView 和 undo 日志进行对比,拿到当前事务可见的数据

了解 BufferPool 缓存机制吗?

参考:

https://blog.csdn.net/mingyuli/article/details/120347093

https://www.processon.com/view/6080de691e08534b2ef0218b

答:

Buffer Pool 本质就是数据库的一个内存组件,Buffer Pool 的大小在 /etc/my.cnf 中进行配置:
在这里插入图片描述

为什么不直接更新磁盘上的数据,而是需要设置一套复杂的机制来执行 SQL 呢?

因为针对数据库数据的读写其实是随机的读写,而对于日志文件的读写是顺序的读写,而顺序读写和随机读写速度差距在 2~3 个数量级,磁盘的顺序 IO 几乎可以和操作内存相媲美。

通过 BufferPool 可以保证每个更新请求都是更新内存 BufferPool,然后顺序写日志文件,同时可以保证各种异常情况下的数据一致性,正是通过这套配置,才能让我们的 MySQL 数据库在较高配置的机器上每秒可以抗下几千的读写请求

为什么数据库数据的读写是随机 IO 呢?

因为数据库存储在磁盘中的数据是会被删除的,我们在写的时候就算一直顺序写,但是如果后边删除了中间的一些数据,那么在之后读就不能顺序读了,因为中间有一些数据已经不存在了

InnoDB SQL 执行流程:

  1. 加载数据页,把需要修改数据所在的数据页,缓存到 BufferPool,BufferPool 中缓存的其实就是一个个的数据页

  2. 修改前记录,写 undo 日志,记录更改前数据,如果事务执行失败,使用 undo 日志进行数据回滚

  3. 更新 Buffer Pool 中的数据

  4. 准备提交事务,写 redo 日志,保存操作记录。redo 日志用来恢复 BufferPool 中的数据

  5. 准备提交事务,写 bin-log 日志,保存操作记录。bin-log 日志用来恢复磁盘数据

  6. 事务提交完成,此时 bin-log 日志写入成功,并在 redo 日志中记录 commit 标记

    redo 日志作用:恢复 BufferPool 中的数据,bin-log 日志是用于恢复磁盘中的数据,其中 redo 日志和 undo 日志是 InnoDB 引擎特有的,而 bin-log 是属于 Server 层的,与引擎无关

    在 redo 日志中记录 commit 标记是为了保证事务提交之后,redo 与 binlog 数据一致,那么想一下如果 BufferPool 缓存中数据更新完毕,但是在数据库将修改后的数据刷到磁盘之前,数据库宕机了,会不会造成 BufferPool 和磁盘的数据不一致呢?

    其实不会,因此当数据库宕机恢复之后,会使用 redo 日志中的数据恢复 BufferPool 中的数据,那么 BufferPool 的数据就是更新后的数据了,等待刷回磁盘即可

  7. 数据持久化,IO 线程不定期把 Buffer Pool 中的数据随机写入到磁盘,完成持久化

MySQL 的预读机制:

当从磁盘上加载一个数据页时,MySQL 可能会连带着把这个数据页相邻的其他数据页也加载到缓存里去。

触发 MySQL 的预读机制的场景?

  1. 线性预读:参数 innodb_read_ahead_threshold 默认值是 56,表示如果顺序的访问了一个区里的多个数据页,访问的数据页的数量超过了这个阈值,就会触发预读机制,把下一个相邻区中的所有数据页都加载到缓存里去

    查看默认值:show variables like 'innodb_read_ahead_threshold'

    在这里插入图片描述

  2. 随机预读:如果 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 部分的缓存页被访问了,才会被移动到链表头部去(这样就

不会出现链表头部数据频繁交替访问,导致频繁移动链表头部数据)。

什么时间将缓存页刷入磁盘呢?

会有一个后台线程运行定时任务,定时将 LRU 链表的冷数据区域尾部的一些缓存页刷入磁盘里去,清空这几个缓存页,将他们加入到 free 链表中(free 链表存放的就是 BufferPool 中的空缓存页的地址)

并且这个后台线程也会在 MySQL 空闲时,将 flush 链表(flush 链表存放的是 BufferPool 中被修改过的缓存页,也称为脏页,脏页都是需要刷回磁盘的)中的缓存页都刷入磁盘中

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/162226.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

2023 现阶段H5的机型适配

个人愚见 现在的主流体验&#xff0c;是大屏手机展示更多的内容&#xff0c;并不着重于放大展示&#xff0c; 所以&#xff0c;外层布局使用vw,百分比&#xff0c;flex&#xff0c;内层直接px就行 比如微信服务页面&#xff0c;大屏下展示更多数据

晨控CK-GW08系列网关控制器与CODESYS软件MODBUSTCP通讯手册

晨控CK-GW08系列是一款支持标准工业通讯协议ModbusTCP的网关控制器,方便用户集成到PLC等控制系统中。系统还集成了8路读写接口&#xff0c;用户可通过通信接口使用Modbus TCP协议对8路读写接口所连接的读卡器进行相对独立的读写操作。 晨控CK-GW08系列网关控制器适用于本公司多…

Flink往Starrocks写数据报错:too many filtered rows

Bug信息 Caused by: com.starrocks.data.load.stream.exception.StreamLoadFailException: {"TxnId": 2711690,"Label": "cd528707-8595-4a35-b2bc-39b21087d6ec","Status": "Fail","Message": "too many f…

Git 安全警告修复手册:解决 `fatal: detected dubious ownership in repository at ` 问题 ️

&#x1f337;&#x1f341; 博主猫头虎 带您 Go to New World.✨&#x1f341; &#x1f984; 博客首页——猫头虎的博客&#x1f390; &#x1f433;《面试题大全专栏》 文章图文并茂&#x1f995;生动形象&#x1f996;简单易学&#xff01;欢迎大家来踩踩~&#x1f33a; &a…

httpclient工具类(支持泛型转换)

1、网上搜到的httpclient工具类的问题&#xff1a; 1.1、如下图我们都能够发现这种封装的问题&#xff1a; 代码繁杂、充斥了很多重复性代码返回值单一&#xff0c;无法拿到对应的Java Bean对象及List对象集合实际场景中会对接大量第三方的OPEN API&#xff0c;下述方法的扩展…

【电路笔记】-谐波

谐波 文章目录 谐波1、概述2、频谱分析3、已知信号4、未知信号5、总结 周期性信号并不总是完美的正弦模式&#xff0c;例如我们之前有关 正弦波的文章之一中介绍的那样。 有时&#xff0c;信号确实可以是简单正弦波的叠加&#xff0c;它们被称为复杂波形。 在本文中&#xff0…

HR的油猴脚本:前程无忧简历关键词统计

介绍 近年来&#xff0c;求职市场变得愈加竞争激烈&#xff0c;雇主和招聘人员需要花费大量的时间来筛选简历&#xff0c;以找到合适的候选人。这个Tampermonkey脚本“HR帮手”为前程无忧&#xff08;51job&#xff09;的HR提供了一种强大的工具&#xff0c;帮助他们快速筛选简…

60V、低 IQ、双通道LTC3892MPUH-2、LTC3892HUH-2、LTC3892IUH-2、LTC3892IUH两相同步降压型 DC/DC 控制器

概述&#xff1a; LTC3892 / LTC3892-2 是一款高性能、双通道降压型 DC/DC 开关稳压控制器&#xff0c;用于驱动全 N 沟道同步功率 MOSFET 级。通过使两个控制器输出级异相运作&#xff0c;可较大限度地降低功率损耗和噪声。 栅极驱动电压可设置在 5V 至 10V 的范围内&…

22款奔驰GLE450加装原厂360全景影像 打破死角

360全景影像影像系统提升行车时的便利&#xff0c;不管是新手或是老司机都将是一个不错的配置&#xff0c;无论是在倒车&#xff0c;挪车以及拐弯转角的时候都能及时关注车辆所处的环境状况&#xff0c;避免盲区事故发生&#xff0c;提升行车出入安全性。 360全景影像包含&…

ActiveMq学习⑨__基于zookeeper和LevelDB搭建ActiveMQ集群

引入消息中间件后如何保证其高可用&#xff1f; 基于zookeeper和LevelDB搭建ActiveMQ集群。集群仅提供主备方式的高可用集群功能&#xff0c;避免单点故障。 http://activemq.apache.org/masterslave LevelDB&#xff0c;5.6版本之后推出了LecelDB的持久化引擎&#xff0c;它使…

mysql迁移data目录(Linux-Centos)

随着时间的推移&#xff0c;mysql的数据量越越大&#xff0c;使用yum默认安装的目录为系统盘 /var/lib/mysql&#xff0c;现重新挂载了一个硬盘&#xff0c;需要做数据目录的迁移到 /mnt/data/。以解决占用系统盘过高情况。 1.强烈建议这种操作。镜像一个一样的Centos系统&…

【文生图】Stable Diffusion XL 1.0模型Full Fine-tuning指南(U-Net全参微调)

文章目录 前言重要教程链接以海报生成微调为例总体流程数据获取POSTER-TEXTAutoPosterCGL-DatasetPKU PosterLayoutPosterT80KMovie & TV Series & Anime Posters 数据清洗与标注模型训练模型评估生成图片样例宠物包商品海报护肤精华商品海报 一些TipsMata&#xff1a;…