HASH_SCAN BUG 的迷惑行为-爱可生
mhr18 2024-10-10 06:51 20 浏览 0 评论
前言
我们知道,MySQL 有一个老问题,当表上无主键时,那么对于在该表上做的DML,如果是以ROW模式复制,则每一个行记录前镜像在备库都可能产生一次全表扫描(或者二级索引扫描),大多数情况下,这种开销都是非常不可接受的,并且产生大量的延迟。
在MySQL 5.6 中提供了一个新的参数:slave_rows_search_algorithms, 可以部分解决无主键表导致的复制延迟问题,其基本思路是对于在一个ROWS EVENT中的所有前镜像收集起来,然后在一次扫描全表时,判断HASH中的每一条记录进行更新。
以上摘自印风大神的文章,具体效果和使用方式可以查看文章:https://yq.aliyun.com/articles/41058。
HASH_SCAN BUG 的迷惑行为
本文不是要继续讨论 slave_rows_search_algorithms 的原理,而是在使用 slave_rows_search_algorithms 参数时遇到一个坑,扑朔迷离的地方在于这不像一个bug,这又是一个bug,最后官方的操作更是让人看不懂。
问题描述
row-based replication,主从数据一致情况下,slave sql 线程报错 Can't find record。
如何复现
配置:
slave_rows_search_algorithms = 'INDEX_SCAN,HASH_SCAN'
binlog_format = ROW
在主库上:
1. CREATE TABLE t1 ( A INT UNIQUE KEY, B INT ); insert into t1 values (1,2);
2. replace into t1 values (1,3),(1,4);
3. 然后从库就会出现报错了。
4. 在从库上:set global slave_rows_search_algorithms='INDEX_SCAN,TABLE_SCAN'; start slave; 问题解决
或者用如下方法避免:
1. 将 UNIQUE KEY 调整为 PRIMARY KEY;
2. 将 replace into tt.t1 values (1,3),(1,4); 调整为 replace into tt.t1 values (1,3);replace into tt.t1 values (1,4);
分析过程:
查看 slaverowssearch_algorithms 参数定义:
The default value is INDEX_SCAN,TABLE_SCAN, which means that all searches that can use indexes do use them, and searches without any indexes use table scans.
To use hashing for any searches that do not use a primary or unique key, set INDEX_SCAN,HASH_SCAN. Specifying INDEX_SCAN,HASH_SCAN has the same effect as specifying INDEX_SCAN,TABLE_SCAN,HASH_SCAN, which is allowed.
Do not use the combination TABLE_SCAN,HASH_SCAN. This setting forces hashing for all searches. It has no advantage over INDEX_SCAN,HASH_SCAN, and it can lead to “record not found” errors or duplicate key errors in the case of a single event containing multiple updates to the same row, or updates that are order-dependent.
(1)根据手册描述,可以理解为:
从库定位数据可选项有 INDEX_SCAN、HASH_SCAN、TABLE_SCAN,优先级是依次递减的。也就是说如果有主键,走 INDEX_SCAN,没主键则根据设置走 HASH_SCAN 还是 TABLE_SCAN(而且如果两者都配了,则优先 HASH_SCAN);无主键设置 INDEX_SCAN,HASH_SCAN,可以提升从库回访效率,降低延迟;如果走了 HASH_SCAN,当对同一行数据同时更新多次时,会导致无法找到行记录。看到这里,手册已经说明原因了。但是矛盾的地方在于手册有推荐使用 INDEX_SCAN,HASH_SCAN 的意思,并且 8.0.2 版本开始的默认值已经修改为:INDEX_SCAN,HASH_SCAN
(2)针对上面的疑问提交SR
Oracle 工程师回应这是 HASH_SCAN 的 bug,修复到了 MySQL8.0.17(还没有正式发布):
It happens when one row is updated twice within an Update_rows_log_event. HASH_SCAN will put both rows in a hash map. Then it iterates over the rows of the table, looks up each row in the hash. If any row is found, it applies the update. Since it only makes one lookup per row, it will miss the second update. In the end, it checks that all rows in the hash were applied and generates an error otherwise. This is what is seen in the bug report.
等等,为什么只修复到 8.0 而没在 5.7 修复?再根据之前就有的疑问,我来脑补一波:
1. 文档写了在某些情况 HASH_SCAN 有这个问题(吐槽:HASH_SCAN 就是优化无主键情况从库复制效率的,但是无主键且对同一行数据同时更新多次时 HASH_SCAN 又会导致从库无法找到记录,那我用还是不用呢?黑人问号.gif),所以暂时我先假设“这不是个 bug”;
2. Oracle 工程师反手甩给我一个 bug 报告,啪啪打脸,官方承认这就是一个 bug;
3. 官方好像也认为有点不对劲,一拍脑袋,咱们只在 8.0 修复,把锅甩给 “8.0.2 的默认值修改成了 HASH_SCAN”。
这个迷惑行为可以用一句经典总结:it's not a bug,it's a feature!
解决方案
1. 给表添加主键(规范必须有主键才是王道);
2. 修改参数 slave_rows_search_algorithms='INDEX_SCAN,TABLE_SCAN';
3. 最符合初衷的做法是升级到 8.0.17,可惜这步对于绝大多数生产环境来说都太大了。
关键字:爱可生、MySQL数据库、数据库运维管理、开源数据库解决方案
相关推荐
- 拥抱开源:微软Azure云平台支持更多Linux系统
-
IT之家讯一直以来,主要依靠软件盈利的大科技公司似乎都与开源站在了对立面上,但微软的Azure云平台再次证明了二者其实可以和谐共赢。微软过去一直都在抵制开源软件,因为它与微软的摇钱树Windows以...
- 微软向Linux开放SQL Server数据库软件
-
ZD至顶网软件频道消息:微软向Linux开放SQLServer数据库软件,并且从3月7日开始向测试者们提供私人预览。微软云及企业业务负责人ScottGuthrie在博客中表示,微软计划在2017...
- 如何主导设计一个亿级高并发系统架构-数据存储架构(三)
-
“架设一个亿级高并发系统,是多数程序员、架构师的工作目标。许多的技术从业人员甚至有时会降薪去寻找这样的机会。但并不是所有人都有机会主导,甚至参与这样一个系统。这个系列我们通过虚构一个这样的系统,一...
- 性能调优实战:Spring Boot 多线程处理SQL IN语句大量值的优化方案
-
环境:SpringBoot3.4.01.简介当我们编写的SQL语句包含有IN语句并且包含大量值时,往往会遇到性能瓶颈,甚至可能导致数据库报错。特别是在处理大数据集时,这种问题尤为突出。大量值的IN语...
- MySQL 如何巧妙解决 Too many connections 报错?
-
1.背景在日常的MySQL运维中,难免会出现参数设置不合理,导致MySQL在使用过程中出现各种各样的问题。今天,我们就来讲解一下MySQL运维中一种常见的问题:最大连接数设置不合理,一旦...
- 用DataX实现两个MySQL实例间的数据同步
-
DataXDataX使用Java实现。如果可以实现数据库实例之间准实时的#数据同步#,可以解决很多问题。例如数据可靠性和高并发的问题。OracleGoldenGate是Oracle提供的一个商业...
- 公司招聘java工程师(程序员)面试考题
-
面试题一、单项选择题(每小题2分,共20分)1:下列属于合法的Java标识符是()A_catB5booksC+staticD-3.141592:在读字符文件Employee.dat时,...
- Java枚举(java枚举用法示例)
-
枚举是一个被命名的整型常数的集合,用于声明一组带标识符的常数。枚举在日常生活中很常见,例如一个人的性别只能是“男”或者“女”,一周的星期只能是7天中的一个等。类似这种当一个变量有几种固定可能的取值...
- JDK 17 - Java 17 的新特性速览(jdk17 loom)
-
JDK17于8月5日进入候选发布阶段,最终候选版本将于8月19日发布。所有功能/JEP集都被冻结以进行目标发布。有10个新功能+2个功能删除+2个功能弃用,还有...
- 一文读懂OSS、NAS、EBS有什么区别?
-
点击链接阅读原文,获取更多技术内容:https://developer.aliyun.com/article/1272997?utm_content=g_1000376104本文主要介绍常用的存储类型...
- DBeaver 25.0.5 发布:SQL 编辑器、导航器升级,新增 Kingbase 支持!
-
近日,DBeaver发布了25.0.5版本!这次更新带来了许多改进和修复,让我们一起来看看都有哪些亮点吧!SQL编辑器:CTE补全和导航支持大幅提升:这对于经常使用CTE(Common...
- 【实测揭秘】数据恢复软件是否有效?按场景分析文件找回概率
-
据IDC统计,全球每年因数据丢失造成的经济损失超过500亿美元,其中68%的案例可通过技术手段挽回部分或全部数据。数据恢复软件作为非专业用户的主要自救工具,数据恢复软件是否有效直接关系到用户能否快速止...
- SQL入门知识篇(sql入门新手教程视频)
-
一、什么是数据库?什么是SQL?1、数据库:存放数据,可以很多人一起使用2、关系数据库:多张表+各表之间的关系3、一张表需要包含列、列名、行4、主键:一列(或一组列),其值能够唯一区分表中的每个行。5...
- postgresql实现跨库查询-dblink的妙用
-
技术导语:用惯了oracle的dblink,转战postgresql,会一时摸不着头脑。本期就重点详细讲解postgresql如何安装dblink模块及如何使用dblink实现跨库查询。安装cont...
- Oracle VM VirtualBox虚拟机软件(oracle vm virtualbox win10)
-
OracleVMVirtualBox是一款完全免费的虚拟机软件,下载银行有提供下载,软件支持安装windows、linux等多个操作系统,让用户可以在一台设备上实现多个操作系统的操作。同时软件有着...
你 发表评论:
欢迎- 一周热门
- 最近发表
- 标签列表
-
- oracle位图索引 (63)
- oracle批量插入数据 (62)
- oracle事务隔离级别 (53)
- oracle 空为0 (50)
- oracle主从同步 (55)
- oracle 乐观锁 (51)
- redis 命令 (78)
- php redis (88)
- redis 存储 (66)
- redis 锁 (69)
- 启动 redis (66)
- redis 时间 (56)
- redis 删除 (67)
- redis内存 (57)
- redis并发 (52)
- redis 主从 (69)
- redis 订阅 (51)
- redis 登录 (54)
- redis 面试 (58)
- 阿里 redis (59)
- redis 搭建 (53)
- redis的缓存 (55)
- lua redis (58)
- redis 连接池 (61)
- redis 限流 (51)