全网最清楚的:MySQL的insert buffer和change buffer 串讲
wptr33 2024-11-08 15:03 34 浏览
目录
- 一、前言
- 二、问题引入
- 2.1、聚簇索引
- 2.2、普通索引
- 三、change buffer存在的意义
- 四、再看change buffer
- 五、change buffer 的限制
- 六、change buffer 相关参数
- 七、查看你的MySQL的change buffer
- 八、灵魂拷问
- 九、参考
一、前言#
终于《为研发同学同学定制的MySQL面试指南》第30篇更新来啦~
说来话长,都说Baidu是养老厂,结果偏偏干出了pdd的感觉。最近工作确实比较忙,然后周六日又想放松一下接连好多周六日都和同学出去游玩。
立个flag吧!后续的更新进度做到每周至少一更。欢迎关注白日梦,干货分享不断~
好!开始啦,做了这么久研发的你,有没有听别人说过、或者在哪里见过insert buffer 、change buffer呢?这篇文章我们一起闲聊一下MySQL的insert buffer、change buffer,彻底揭开这两个名词的面纱!
二、问题引入#
在白日梦看来,如果你想更好的理解 insert buffer、change buffer。首先你的先掌握一些前置的知识,比如MySQL索引的相关知识。所以不要着急,我们一点点展开话题,从你数据的知识过度到insert buffer、change buffer上去,你会发现豁然开朗。
2.1、聚簇索引#
首先我们回顾一下MySQL的聚簇索引,这个东西大家肯定不陌生吧!我打赌在做的各位面试前都会背一背什么是聚簇索引。
大家可以看下面这张图,它就是对B+tree的抽象。它有很多特性,在这篇文章中只需要知道如下几个就好了
- 它是一个B+tree。
- 我们管这棵树的叶子结点叫做数据页。
- 叶子结点中存储的数据行是一个全集,怎么解释这个全集呢?比如数据表就3列,id、name、age。所谓的全集就是说:每行数据都有id、name、age这3列。
- 我们管非叶子结点叫做索引页。
而且我跟大家讲哦,这棵B+tree是会被存储在Disk中的。如果你不能很好的理解的话,可以读一下下面的两段话:
比如一条update sql想修改id = 999的数据行,那它会怎么操作数据页呢?简单来说就是:首先会检查一下buffer pool中有没有包含这条数据的数据页。如果有的话,直接update。如果没有的话进行一次磁盘IO把该数据页加载进内存,然后将其update。然后这时的数据页也就变成了脏页。等后续其它机制将该数据页刷新回Disk。完成内存和数据。
读上面的这段话,你要重点感受一下:数据页从磁盘到Buffer Pool中的这个过程(最终会被挂载在B+tree的叶子结点上)
其实你类比着数据页来看,对于B+tree的非叶子结点来说也是一样的。上面我说了,我们管非叶子结点叫做索引页。为啥这样说呢?其实本质上非叶子结点也是数据页,只不过它里面存储的数据是索引数据。而且和普通的数据页一样,当你需要它而且它还不在内存中时,进行磁盘操作将其读取内存中。
2.2、普通索引#
普通的索引也就是我们常说的二级索引、联合索引等等。
比如我们将name列设置成index的话,那么MySQL就会为我们这个索引单独创建一个B+Tree。(是的!它是独立于主键索引之外的另一颗B+Tree)。而且你注意一下如下几点:
- 和聚簇索引一样的是,我们管它的非叶子结点叫做:索引页
- 它的叶子结点中存储的并不是所有的列的全集。比如我们对name列创建索引,那么它的叶子节点中存储的就是id、name两列。并会按照name排序。
三、change buffer存在的意义#
了解了上面的索引相关的前置知识点再来看insert buffer和change buffer那其实就很简单了。
我们这一小节来看一下change buffer存在的意义:
其实说白了其实insert buffer也好,还是change buffer也好,它们其实就是MySQL在我们对非唯一的二级索引进行DML(删除行、写入行、修改行)操作时作出的优化逻辑。目的就是让MySQL的性能更好。
比如还是我们这个例子:表里面有3列。id、name、age。然后id是主键、name是非唯一的二级索引。
一条update sql:update xx set name = "赐我白日梦" where name = “白日梦”打过来之后,执行流程大概就像下面这样:
1、检查需要被update的数据是否在buffer pool中。
2、如果在buffer pool中直接将其update。
3、如果不在buffer pool中,进行磁盘的IO操作,将其读取内存中,再把它update。
现在的问题是,name列是个索引列。上文也说了,既然是索引列就意味着需要为它单独创建一颗B+Tree。
那你的update sql要做修改,那是不是会分成两个大的步骤
1、Step1: 对buffer pool中的数据页中的数据进行update。
2、Step2: 维护为name单独创建的B+Tree。
你想呀既然MySQL要优化我们对非唯一的二级索引的DML操作,肯定要有个需要优化的点吧!
而这里的Step2,就是insert buffer和change buffer 存在的意思所在!
为啥这样说呢?因为在本篇文章的开头我们提到了,B+tree也是存储在Disk中的,那它肯定就难免发生随机磁盘IO。
或者你想一下:你只是想update 几条数据。假设运气很不好这几条都没有在buffer pool中。那没办法,我们只能去读磁盘。但是更不巧的,涉及到的二级索引页竟然也没有在内存中,我们竟然还要同步等待这一次随机磁盘IO!!!
四、再看change buffer#
change buffer的本质上其实也是一块内存。
比如你的:insert、delete、update等DML操作需要用到的二级索引页(注意是二级索引页,具体就比如说为name列这个二级索引创建的B+Tree的叶子节点,而不是Buffer pool中的普通数据页)
就是当这些二级索引页不在内存中时,你对它们的操作会被缓存在change buffer中(目的是省去这次随机的磁盘IO)。等之后MySQL空闲了、或者是MySQL关闭前、或者是在读取操作时再将这部分缓存操作merge到B+Tree中。
五、change buffer 的限制#
这个现实其实已经说过了
1、首先的要求是二级索引。如果不是二级索引到话,那前面change buffer存在意义又是什么呢?没有啥可优化的地方。那不如不要这个change buffer
2、要求二级索引不能唯一。这个很好理解。如果name列是唯一的。那我每次insert 之前是不是都必须去看下内存、Disk上到底有没有已经存在的相同值的索引。这也就意味着这个insert 操作其实是不能被缓存的!必须立即知道到底能否insert 成功。对吧!不这样的话,你打算返回给客户端什么结果呢?
六、change buffer 相关参数#
参数:innodb_change_buffer_max_size
作用:控制change buffer能占用buffer pool总内存的比例
范围:默认25(表示change buffer最大能占用其25%的内存),最大50。
参数:innodb_change_buffering
作用:控制change buffer对那些dml起作用
可选参数:all(insert、delete、update)、none(不缓存任何操纵)、inserts、deletes、purges
七、查看你的MySQL的change buffer#
Copy# 命令
SHOW ENGINE INNODB STATUS\G
# 查看如下部分
-------------------------------------
INSERT BUFFER AND ADAPTIVE HASH INDEX
-------------------------------------
Ibuf: size 1, free list len 0, seg size 2, 0 merges
merged operations:
insert 0, delete mark 0, delete 0
discarded operations:
insert 0, delete mark 0, delete 0
Hash table size 4425293, used cells 32, node heap has 1 buffer(s)
13577.57 hash searches/s, 202.47 non-hash searches/s
# insert:insert buffer
# delete mask:delete buffer
# delete :purge buffer
# discarded operations:当change buffer发生merge时,数据表被删除了!无需再merge
八、灵魂拷问#
如果你能回答上这个问题,说明你真的理解了change buffer!
问:
我开启change buffer 之后,现在要删除一个非唯一的二级辅助索引数据行,比如就删除name=Tom的行,并且这个索引页不在内存中……接下来会发生什么?
按照change buffer的作用来说,是不是当索引页不在内存中时,不去读盘,而是会把这个删除操作写到change buffer 中?
那问题又来了,既然你是把这个操作写到了change buffer中,那你返回给客户端的影响行数怎么算出来的呢?你都没有读读磁盘,万一磁盘上都没你要删除的数据呢…… 你告诉客户端,删除成功了,影响行数为1?
答:其实客户端每次都能得到正确的影响行数!不错,change buffer中是把缓存了你的delete操作,但是buffer pool是没有被影响的呀,如果buffer pool中没有这个name=Tom的行,它依然会去读磁盘的!你品一品,buffer pool和change buffer是两块缓存哦~
相关推荐
- 开发者必看的八大Material Design开源项目
-
MaterialDesign是介于拟物和扁平之间的一种设计风格,自从它发布以来,便引起了很多开发者的关注,在这里小编介绍在Android开发者当中里最受青睐的八个MaterialDesign开源项...
- 另类插这么可爱,一定是…(另类t恤)
-
IT之家(www.ithome.com):另类插图:这么可爱,一定是…OSXMavericks和Yosemite打破了苹果对Mac操作系统传统的命名方式,使用加州的某些标志性景点来替换猫...
- Android常用ADB命令(安卓adb工具是什么)
-
杀死应用①根据包名获取APP的PIDadbshellps|grep应用包名②执行kill命令...
- 微软Mac版PowerPoint测试Reading Order Pane功能
-
IT之家5月20日消息,微软公司昨日(5月19日)发布博文,邀请Microsoft365Insiders成员,测试macOS新版PowerPoint演示文稿应用,重点引入...
- Visual Studio跨平台开发实战(4):Xamarin Android控制项介绍
-
前言不同于iOS,Xamarin在VisualStudio中针对Android,可以直接设计使用者界面.在本篇教学文章中,笔者会针对Android的专案目录结构以及基本控制项进行介绍,包...
- 用云存储30分钟快速搭建APP,你信吗?
-
背景不管你承认与否,移动互联的时代已经到来,这是一个移动互联的时代,手机已经是当今世界上引领潮流的趋势,大型的全球化企业和中小企业都把APP程序开发纳入到他们的企业发展策略当中。但随着手机APP上传的...
- 谷歌P图神器来了!不用学不用教,输入一句话,分分钟给结果
-
Pine发自凹非寺量子位|公众号QbitAI当你拍照片时,“模特不好好配合”怎么办?...
- iOS文本编辑控件UITextField和UITextVie
-
记录一个菜鸟的IOS学习之旅,如能帮助正在学习的你,亦枫不胜荣幸;如路过的大神如指教几句,亦枫感激涕淋!细心的朋友可能已经注意到了,IOS学习之旅系列教程在本篇公众号的文章中,封面已经换成美女图片了,...
- Android入门图文教程集锦(android 入门教程)
-
Android入门视频教程集锦AndroidStudio错误gradientandroid:endXattributenotfound...
- 如何使用Android自定义复合视图(如何使用android自定义复合视图)
-
在最近的一个客户应用中,我遇到了一个需求,根据选定的值来生成指定数量的编辑框字段,这样用户可以输入人物信息。最初我的想法是把这些逻辑放到Fragment中,只是根据选中值的变化来向线性布局容器中增加编...
- 原生安卓开发app的框架frida常用关键代码定位
-
前言有时候可能会对APP进行字符串加密等操作,这样的话你的变量名等一些都被混淆了,看代码就可能无从下手...
- 教程10 | 三分钟搞定一个智能输入法程序
-
一案例描述1、考核知识点网格布局线性布局样式和主题Toast2、练习目标掌握网格布局的使用掌握Toast的使用掌握线性布局的使用...
- (Android 8.1) 功能与新特性(android的功能)
-
和你一起终身学习,这里是程序员AndroidAndroid8.1(API级别27)为用户和开发人员引入了各种新特性和功能。本文档重点介绍了开发人员的新功能。通过本章阅读,您将获取到以下内容:Andr...
- 怎样设置EditText内部文字被锁定不可删除和修改
-
在做项目的时候,我曾经遇到过这样的要求,就是跟百度贴吧客户端上的一样,在回复帖子的时候,在EditText中显示回复人的名字,而且这个名字不可以修改和删除,说白了就是不可操作,只能在后面输入内容。在E...
- 如何阻止 Android 活动启动时 EditText 获得焦点
-
技术背景在Android开发中,当活动启动时,EditText有时会自动获得焦点并弹出虚拟键盘,这可能不是用户期望的行为。为了提升用户体验,我们需要阻止...
- 一周热门
-
-
C# 13 和 .NET 9 全知道 :13 使用 ASP.NET Core 构建网站 (1)
-
因果推断Matching方式实现代码 因果推断模型
-
git pull命令使用实例 git pull--rebase
-
面试官:git pull是哪两个指令的组合?
-
git 执行pull错误如何撤销 git pull fail
-
git fetch 和git pull 的异同 git中fetch和pull的区别
-
git pull 和git fetch 命令分别有什么作用?二者有什么区别?
-
git pull 之后本地代码被覆盖 解决方案
-
还可以这样玩?Git基本原理及各种骚操作,涨知识了
-
git命令之pull git.pull
-
- 最近发表
-
- 开发者必看的八大Material Design开源项目
- 另类插这么可爱,一定是…(另类t恤)
- Android常用ADB命令(安卓adb工具是什么)
- 微软Mac版PowerPoint测试Reading Order Pane功能
- Visual Studio跨平台开发实战(4):Xamarin Android控制项介绍
- 用云存储30分钟快速搭建APP,你信吗?
- 谷歌P图神器来了!不用学不用教,输入一句话,分分钟给结果
- iOS文本编辑控件UITextField和UITextVie
- Android入门图文教程集锦(android 入门教程)
- 如何使用Android自定义复合视图(如何使用android自定义复合视图)
- 标签列表
-
- git pull (33)
- git fetch (35)
- mysql insert (35)
- mysql distinct (37)
- concat_ws (36)
- java continue (36)
- jenkins官网 (37)
- mysql 子查询 (37)
- python元组 (33)
- mybatis 分页 (35)
- vba split (37)
- redis watch (34)
- python list sort (37)
- nvarchar2 (34)
- mysql not null (36)
- hmset (35)
- python telnet (35)
- python readlines() 方法 (36)
- munmap (35)
- docker network create (35)
- redis 集合 (37)
- python sftp (37)
- setpriority (34)
- c语言 switch (34)
- git commit (34)