mysqlinnodb锁使用教程(MySQL Innodb关键特性之插入缓冲insert buffer)
mysqlinnodb锁使用教程
MySQL Innodb关键特性之插入缓冲insert buffer什么是insert buffer?
插入缓冲,也称之为insert buffer,它是innodb存储引擎的关键特性之一,我们经常会理解插入缓冲时缓冲池的一个部分,这样的理解是片面的,insert buffer的信息一部分在内存中,另外一部分像数据页一样,存在于物理页中。
在innodb中,我们知道,如果一个表有自增主键,那么对于这个表的默认插入是非常快的,注意,这里的主键是自增的,如果不是自增的,那么这个插入将会变成随机的,就可能带来数据页分裂的开销,这样,插入就不是顺序的,就会变慢。还有一种情况,就是如果我们插入的id不是顺序的,而是随机的,那么即使有自增主键,那么插入的速度也不会特别快。
如果我们定义了一个表,包含一个主键和一个非聚集索引,如下:
|
create table t( a int auto_increment, b varchar (30), primary key (a), key (b) ); |
当我们按照主键a进行插入的时候,对于非聚集索引,也就是常说的二级索引b,它的插入不是顺序的,插入性能必然会下降。
innodb存储引擎针对这种情况,设计了insert buffer,对于非聚集索引的插入或者更新操作,不是每一次插入到索引页中,而是先判断插入的非聚集索引页是否在缓冲池中,如果在,则直接插入,如果不在,则先放入一个insert buffer中,告诉数据库这个非聚集的索引已经插入到了叶子节点,实际上并没有插入,只是存放在另外一个位置,然后再以一定的频率和情况进行insert buffer和辅助索引叶子节点合并操作。这种时候,经常能将多条记录的插入合并到一个操作中,这样就大大提高了非聚集索引离散插入的性能。
insert buffer的触发条件?
insert buffer需要满足两个条件才能被使用,第一,索引是辅助索引,也就是二级索引,第二,索引不是唯一的。当满足上述两个条件的时候,就可以使用insert buffer,从而提高数据库的插入操作性能。
这里需要注意,如果在程序进行了大量操作的时候发生了mysql数据库的宕机,那么肯定有大量的insert buffer没有合并到实际的非聚集索引中去,恢复可能会造成很长的时间。
为什么不能是唯一索引?
之所以不支持唯一索引,是因为如果辅助索引是唯一索引,那么在插入时需要校验唯一性,校验唯一性的时候就会发生离散读取,从而又增加了开销,那么insert buffer得不偿失。
我们可以通过show engine innodb status来查看insert buffer的使用情况,如下:
|
mysql --root@localhost:dms_alimetadata 20:35:24>>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 |
其中size代表了已经合并记录页的数量,free list len代表了空闲列表的长度,seg size显示了当前insert buffer的大小为2*16kb
引入change buffer的概念
最新的mysql5.7已经支持change buffer,事实上,它在innodb 1.0.x版本已经引入,这个change buffer 可以理解为insert buffer的升级,也就是对常见的dml语言都可以进行缓冲,包含insert delete以及update,对应的分别是insert buffer,delete buffer以及purge buffer。
当然,change buffer的使用对象仍然是非唯一的辅助索引。
这里我们以update操作为例,update的过程可以拆分为两个部分:
第一个部分是将记录的delete_mask标记为删除,如果你不了解delete_mask,可以在4月9号的文章中去看。第二个部分是真正的将记录删除。
而delete buffer对应的是update的第一个过程,purge buffer对应的是第二个部分。
在innodb中,我们可以通过参数innodb_change_buffering来开启buffer的各种选项,该参数可选的值为inserts,deletes,purges,changes,all,none等,其中inserts,deletes和purges就是前面讨论过的情况,changes表示开启inserts和deletes,all表示开启所有,默认的参数如下:
|
mysql --root@localhost:dms_alimetadata 21:13:37>>show variables like '%buffering%'; + -------------------------+-------+ | variable_name | value | + -------------------------+-------+ | innodb_change_buffering | all | + -------------------------+-------+ 1 row in set (0.01 sec) |
我们还可以通过innodb_change_buffer_max_size来控制change_buffer的最大使用内存数量,该参数的默认值是25,也就是1/4,示例如下:
|
mysql --root@localhost:dms_alimetadata 21:20:52>>show variables like '%innodb_change_buffer_max_size%'; + -------------------------------+-------+ | variable_name | value | + -------------------------------+-------+ | innodb_change_buffer_max_size | 25 | + -------------------------------+-------+ 1 row in set (0.00 sec) |
在上面的show engine innodb status命令的输出结果中,显示了merged operation和discarded operation,其中insert 表示insert buffer的操作次数,delete mark表示delete buffer的操作次数,而delete表示purge buffer的操作次数,discarded operation表示当change buffer发生merge时,表已经被删除,此时就无需进行合并。
insert buffer的实现?
insert buffer的数据结构是一棵b+树,类似聚集索引一样,全局只有一棵insert buffer b+树,它负责对所有的表进行insert buffer,而这棵b+树放在共享表空间中,也就是ibdata1文件中,因此,试图通过ibd文件恢复表数据的时候可能会出现check table失败,原因是表的辅助索引中的数据可能还在insert buffer中,所以通过ibd文件恢复文件之后,还需要进行repair table操作来重建表上的辅助索引。
insert buffer既然是一棵树,那么必定有叶子节点和非叶子节点,非叶子节点存放的是查询的search key值,它的构造如下:
|
+ ---------+------------+-------+ | space | marker | value | + ---------+------------+-------+ |
这个结构一共占用9个字节,其中,space表示待插入的记录所在的表的表空间id,这个id是每个表都要有的唯一的id,其中space占用4个字节,marker占用1个字节,用来兼容老版本的insert buffer,offset占用4个字节,表示页所在的偏移量。
辅助索引的插入过程?
当一个辅助索引要插入到数据页的时候,如果这个数据页不在缓冲池中,那么innodb会根据规则构造一个search key,接下来将这个记录插入到insert buffer的b+树里面去,插入的过程中,需要对这个记录进行一些构造,最终插入的结果是类似下面这样的一条记录:
|
+ ---------+------------+-------+------------+------+-------+------+-------+ | space | marker | value | metadata | | | | | + ---------+------------+-------+------------+------+-------+------+-------+ |
可以发现,最后面多了一个metadata的字段和4个其他的字段,先来说说metadata的字段,它占用4个字节,它用来排序每个记录进入insert buffer的顺序,从第5列开始,就是实际插入记录的各个字段的值了,因此和单纯的数据记录相比,insert buffer需要额外13个字节的开销。
为了保证每次merge insert buffer成功,需要设置一个特殊的数据页来标记每个辅助索引页的可用空间,这个数据页的类型为insert buffer bitmap,这个页可以追踪很多辅助索引页的可用空间。这里简单了解一下,下面会解释它的用法。
merged insert buffer的时机?
我们前面已经知道,当插入记录的辅助索引页不在缓冲池中的时候,需要将辅助索引记录插入到这棵b+树中,后续会从insert buffer中往真正的辅助索引中进行合并,那么什么时候进行合并呢?
1、辅助索引页被读取到缓冲池的时候
2、insert buffer bitmap追踪到该辅助索引页已经没有足够的可用空间时,一般的阈值是辅助索引页空间的1/32
3、master thread每秒执行一次merge insert buffer的操作
以上就是mysql innodb关键特性之插入缓冲(insert buffer)的详细内容,更多关于innodb特性之插入缓冲的资料请关注开心学习网其它相关文章!
原文链接:https://mp.weixin.qq.com/s/FoSmM9eS_CMnL7-SYqLpqQ
- mysql常用存储方案及基本原理(详解分析MySQL8.0的内存消耗)
- mysql8.0设置root密码(MySQL8.0.23版本的root密码重置最优解法)
- mysql数据库使用规则(mysql数据库基本语法及操作大全)
- mysql的连接池名称如何查看(如何使用mysqladmin获取一个mysql实例当前的TPS和QPS)
- mysql explain的用法
- MySQL DATE_FORMAT()用法
- mysql5.7.19下载及安装教程(Apache2.2.16+PHP5.3.3+MySQL5.1.49的配置方法)
- apache搭建php环境(Windows上安装Apache2、PHP5、MySQL5及与Resin配合实现多系统之整合)
- mysql面试题及答案100题(几个MySQL高频面试题的解答)
- mysql拆分成多行(mysql单字段多值分割和合并的处理方法)
- mysql开启审计日志会导致性能下降(MySQL 一则慢日志监控误报的问题分析与解决)
- centos7可以装mysql吗(详解腾讯云CentOS7.0使用yum安装mysql及使用遇到的问题)
- mysqlint后面的4是什么意思(MySQL中intn后面的n到底代表的是什么意思)
- mysql主从复制步骤(MySQL8 主从复制踩坑指南)
- mysqldecimal类型转换(mysql中decimal数据类型小数位填充问题详解)
- mysql innodb存储原理(mysql innodb的重要组件汇总)
- 少儿口才表达影响未来一生,50首经典绕口令和孩子玩出聪明大脑(少儿口才表达影响未来一生)
- 玩网游居然让人更友善 很难以让人置信(玩网游居然让人更友善)
- 学好汉语拼音,从娃娃绕口令抓起,平时还是要多练 收藏好(从娃娃绕口令抓起)
- 仙女们的私藏鲜法大PK 鲜香切块牛肉(仙女们的私藏鲜法大PK)
- 天热没胃口 这道菜开胃又下饭,2个小技巧新手一学就会(这道菜开胃又下饭)
- 指天椒紫苏爆炒牛肉(指天椒紫苏爆炒牛肉)
热门推荐
- css语言是干嘛的(Css预编语言及区别详解)
- css line-height(CSS中的line-height行高属性学习教程)
- dedecms关键词功能(DedeCms 5.7 代码高亮实现方法)
- https服务器怎么打开(网站服务器配置是选HTTP还是HTTPS?)
- 使用docker对集群进行管理(使用docker搭建kong集群操作)
- web压力测试工具app(十款Web服务器性能压力测试工具)
- sql server中dense_rank和row_number的区别
- dede联动菜单样式(dede标签云如何生成不同颜色、不同大小的tag标签)
- mysql 索引怎么实现(Mysql中索引和约束的示例语句)
- dedecms指定栏目授权(dedecms搜索结果页实现按频道模型显示不同结果模板的方法)
排行榜
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9