最近在网上看到一些文章里说:“change buffer 只适用于非唯一索引页。”其实这个观点是错的,先来看看官方文档对 change buffer 的介绍:

文档地址:https://dev.mysql.com/doc/refman/8.0/en/innodb-change-buffer.html

The change buffer is a special data structure that caches changes to secondary index pages when those pages are not in the buffer pool.

这里的意思是,缓存那些不在 buffer pool 中的二级索引页,并不是指非唯一的二级索引。那具体使用 change buffer 的条件是什么?其实具体使用条件主要汇集在以下五点:

  • 用户设置选项 innodb_change_buffering。

  • 在 mysql 的索引结构中,只有叶子结点才存储数据。因此有叶子节点才考虑是否使用 ibuf。

  • 如上面文档显示的一样,change buffer 只能缓存二级索引页,所以对于聚集索引,不可以缓存操作。聚簇索引页是由 Innodb 引擎将数据页加载到 Buffer Pool中(这个查找过程是顺序 I/O),然后进行数据记录插入或者更新、删除。

  • 因为唯一二级索引(unique key)的索引记录具有唯一性,因此无法缓存插入和更新操作,但可以缓存删除操作;

  • 表上没有 flush 操作,例如执行 flush table for export 时,不允许对表进行 ibuf 缓存 (通过 dict_table_t::quiesce 进行标识)

接下来我们结合源码和文档来看看具体操作。

源码地址:GitHub - mysql/mysql-server: MySQL Server, the world's most popular open source database, and MySQL

先看第一点设置选项尾 innodb_change_buffering,它能够针对三种类型的操作 INSERT、DELETE-MARK 、DELETE 进行缓存,三者对应 dml 语句关系如下:

  • INSERT 操作:插入二级索引。

  • 先进行 DELETE-MARK 操作,再进行INSERT操作:更新二级索引。

  • DELETE-MARK 操作:删除二级索引

// 代码路径:storage/innobase/include/ibuf0ibuf.h

/* Possible operations buffered in the insert/whatever buffer. See
ibuf_insert(). DO NOT CHANGE THE VALUES OF THESE, THEY ARE STORED ON DISK. */
typedef enum {
IBUF_OP_INSERT = 0,
IBUF_OP_DELETE_MARK = 1,
IBUF_OP_DELETE = 2, /* Number of different operation types. */
IBUF_OP_COUNT = 3
} ibuf_op_t; /** Combinations of operations that can be buffered.
@see innodb_change_buffering_names */
enum ibuf_use_t {
IBUF_USE_NONE = 0,
IBUF_USE_INSERT, /* insert */
IBUF_USE_DELETE_MARK, /* delete */
IBUF_USE_INSERT_DELETE_MARK, /* insert+delete */
IBUF_USE_DELETE, /* delete+purge */
IBUF_USE_ALL /* insert+delete+purge */
};

此外 innodb_change_buffering 还可以通过设置其他选项来进行相应的缓存操作:

  • all:默认值,默认开启 buffer inserts、delete-marking operations、purges。

  • none:不开启 change buffer。

  • inserts:只是开启 buffer insert 操作。

  • deletes:只是开 delete-marking 操作。

  • changes:开启 buffer insert 操作和 delete-marking 操作。

  • purges:对只是在后台执行的物理删除操作开启 buffer 功能。

第二点还需要大家进行判断条件即可,所以就不进行扩展讲解了,我们来细说一下第三点。

第三点的具体参考函数为 ibuf_should_try,它满足 ibuf 缓存条件后,会使用两种模式去尝试获取数据页。

这里说明一下,在 MySQL5.5 之前的版本中,由于只支持缓存 insert 操作,所以最初叫做 insert buffer,只是后来的版本中支持了更多的操作类型缓存,才改叫 change buffer,但是代码中与 change buffer 相关的 函数或变量还是以 ibuf 前缀开头。

下面是函数的具体实现,地址在:storage/innobase/include/ibuf0ibuf.ic

/** A basic partial test if an insert to the insert buffer could be possible and
recommended. */
static inline ibool ibuf_should_try(
dict_index_t *index, /*!< in: index where to insert */
ulint ignore_sec_unique) /*!< in: if != 0, we should
ignore UNIQUE constraint on
a secondary index when we
decide */
{
return (innodb_change_buffering != IBUF_USE_NONE && ibuf->max_size != 0 &&
index->space != dict_sys_t::s_dict_space_id &&
!index->is_clustered() && !dict_index_is_spatial(index) &&
!dict_index_has_desc(index) &&
index->table->quiesce == QUIESCE_NONE &&
(ignore_sec_unique || !dict_index_is_unique(index)) &&
srv_force_recovery < SRV_FORCE_NO_IBUF_MERGE);
}

上面加粗和标红的地方就是对唯一二级索引的判断的地方,意思是:

  • 当 ignore_sec_unique 这个变量为 0 时,如果修改的是唯一二级索引记录,就不能使用。

  • 当 ignore_sec_unique 这个变量为 1 时,如果修改的是唯一二级索引记录,还可以试着使用一下。

ignore_sec_unique 的取值在:storage/innobase/btr/btr0cur.cc

    if (btr_op != BTR_NO_OP &&
ibuf_should_try(index, btr_op != BTR_INSERT_OP)) {
/* Try to buffer the operation if the leaf
page is not in the buffer pool. */ fetch = btr_op == BTR_DELETE_OP ? Page_fetch::IF_IN_POOL_OR_WATCH
: Page_fetch::IF_IN_POOL;
}

其中红框中的 btr_op 指的是本次修改的具体操作是什么,也就是:

当此次具体的修改操作是 INSERT 操作时,ignore_sec_unique 为 0,也就是当修改的是唯一二级索引记录时,不可以使用 ibuf。

  • 当此次具体的修改操作不是 INSERT 操作时,ignore_sec_unique 为 1,也就是当修改的是唯一二级索引记录时,可以试着使用 ibuf。

  • 可以看到当 ibuf_should_try 函数返回 1 时,也就是可以试着用一下 ibuf,那么就把读取 buffer pool 中页面的模式改一下。

最后总结一下,看完了本文相信大家都能比较明确的意识到,网上说只有非唯一索引才能使用 change buffer 的说法,毫无疑问是错的。只要满足了其它 4 个条件,对唯一索引进行的删除操作完全可以使用 change buffer 优化。

推荐阅读

javaScript 内存管理机制

130 行代码搞定核酸统计,程序员在抗疫期间的大能量

Change Buffer 只适用于非唯一索引页?错的更多相关文章

  1. mysql 区间锁 对于没有索引 非唯一索引 唯一索引 各种情况

    The locks are normally next-key locks that also block inserts into the "gap" immediately b ...

  2. 唯一索引与非唯一索引区别(UNIQUE INDEX, NON-UNIQUE INDEX)

    索引是我们经常使用的一种数据库搜索优化手段.适当的业务操作场景使用适当的索引方案可以显著的提升系统整体性能和用户体验.在Oracle中,索引有包括很多类型.不同类型的索引适应不同的系统环境和访问场景. ...

  3. 普通索引和唯一索引如何选择(谈谈change buffer)

    假设有一张市民表(本篇只需要用其中的name和id_card字段,有兴趣的可以翻看“索引”篇,里面有建表语句) 每个人都有一个唯一的身份证号,且业务代码已经保证不会重复. 由于业务需求,市民需要按身份 ...

  4. 【MySQL 读书笔记】普通索引和唯一索引应该怎么选择

    通常我们在做这个选择的时候,考虑得最多的应该是如果我们需要让 Database MySQL 来帮助我们从数据库层面过滤掉对应字段的重复数据我们会选择唯一索引,如果没有前者的需求,一般都会使用普通索引. ...

  5. mysql-5.7 innodb change buffer 详解

    一.innodb change buffer 介绍: 1.innodb change buffer 是针对oltp场景下磁盘IO的一种优化(我也感觉这个不太像人话,但是它又非常的准确的说明 innod ...

  6. SQLServer之创建唯一非聚集索引

    创建唯一非聚集索引典型实现 唯一索引可通过以下方式实现: PRIMARY KEY 或 UNIQUE 约束 在创建 PRIMARY KEY 约束时,如果不存在该表的聚集索引且未指定唯一非聚集索引,则将自 ...

  7. 对于唯一索引使用唯一条件搜索, InnoDB 只锁定找到的index record,不是它之前的区间

    | test100 | CREATE TABLE `test100` ( `sn` int(11) NOT NULL AUTO_INCREMENT COMMENT '自增编号', `phoneNo` ...

  8. SQL有三个类型的索引,唯一索引 不能有重复,但聚集索引,非聚集索引可以有重复

    重要: (1) SQL如果创建时候,不指定类型那么默认是非聚集索引 (2) 聚集索引和非聚集索引都可以有重复记录,唯一索引不能有重复记录. (3) 主键 默认是加了唯一约束的聚集索引,但是也可以在主键 ...

  9. SQL存储原理及聚集索引、非聚集索引、唯一索引、主键约束的关系(补)

    索引类型 1.          唯一索引:唯一索引不允许两行具有相同的索引值 2.          主键索引:为表定义一个主键将自动创建主键索引,主键索引是唯一索引的特殊类型.主键索引要求主键中的 ...

随机推荐

  1. JavaScript读取剪贴板中的表格生成图片

    原文 JavaScript读取剪贴板中的表格生成图片 演示地址 你可以访问下面的地址体验每个demo https://fairyever.github.io/excel-to-image-demo/ ...

  2. python-使用函数求特殊a串数列和

    给定两个均不超过9的正整数a和n,要求编写函数fn(a,n) 求a+aa+aaa++⋯+aa⋯aa(n个a)之和,fn须返回的是数列和 函数接口定义: 1 fn(a,n) 2 其中 a 和 n 都是用 ...

  3. throws子句在继承当中overrride时有什么规则

    8.throws子句在继承当中overrride时的规则 马克-to-win:当子类方法override父类方法时,throws子句不能引进新的checked异常.换句话说:子类override方法的 ...

  4. pytest-mark 参数化

    在类前或用例前用pytest.mark.parametrize ,可进行参数化 传参方式比较灵活,有很多种,下面是列出的几种方式,其他的可自行研究 @pytest.mark.parametrize(& ...

  5. 基于Debian搭建Hyperledger Fabric 2.4开发环境及运行简单案例

    相关实验源码已上传:https://github.com/wefantasy/FabricLearn 前言 在基于truffle框架实现以太坊公开拍卖智能合约中我们已经实现了以太坊智能合约的编写及部署 ...

  6. 企业应用架构研究系列二十七:Vue3.0 之环境的搭建与Vue Antd Admin探索

    开发前端需要准备一些开发工具,这些工具怎么安装就不详细描写了,度娘一些很多很多.主要把核心的开发工具列表一些,这些资源也是非常容易找到和安装的. Node 安装:https://nodejs.org/ ...

  7. java的collection类

    collection来源于java.util包. Collection 接口常用的方法 size():返回集合中元素的个数 add(Object obj):向集合中添加一个元素 addAll(Coll ...

  8. Jx.Cms开发笔记(二)-系统登录

    界面 此界面完全抄了BootstrapAdmin css隔离 由于登录页面的css与其他页面没有什么关系,所以为了防止其他界面的css被污染,我们需要使用css隔离. css隔离需要在_Host.cs ...

  9. 2022.02.27 CF811E Vladik and Entertaining Flags

    2022.02.27 CF811E Vladik and Entertaining Flags https://www.luogu.com.cn/problem/CF811E Step 1 题意 在一 ...

  10. zookeeper篇-zk的选举机制

    点赞再看,养成习惯,微信搜索「小大白日志」关注这个搬砖人. 文章不定期同步公众号,还有各种一线大厂面试原题.我的学习系列笔记. 说说zk的选举机制 基础概念 zxid=事务id=一个时间戳,代表当前事 ...