slave_rows_search_algorithms默认值为'TABLE_SCAN,INDEX_SCAN',不含HASH_SCAN是出于兼容性与安全性的保守设计;其核心限制在于HASH_SCAN要求binlog_row_image=FULL且表含主键或唯一键,否则会fallback或报错HA_ERR_KEY_NOT_FOUND。

slave_rows_search_algorithms 并不是 MySQL 8.0 主从复制“默认关闭”的参数——它始终启用且有默认值,只是默认值不包含 HASH_SCAN,容易让人误以为“被关闭”。
MySQL 5.6.6 引入该参数后,其默认值一直是 'TABLE_SCAN,INDEX_SCAN'(注意:不是空、不是 OFF、也不是 DISABLED)。所谓“没开 HASH_SCAN”,是出于兼容性与安全性的保守设计,而非功能被禁用。
slave_rows_search_algorithms 的默认值为什么不含 HASH_SCAN?
slave_rows_search_algorithms 控制从库在 ROW 格式复制中如何定位待更新/删除的行。它的取值是逗号分隔的算法组合,MySQL 按顺序尝试:
-
TABLE_SCAN:全表扫描,最慢但最稳妥 -
INDEX_SCAN:用非唯一索引查找,需回表 -
HASH_SCAN:基于 event 中的 before_image 构建哈希表,仅适用于 主键或唯一键完全匹配 的场景
默认不启用 HASH_SCAN 的核心原因:
-
HASH_SCAN要求 binlog 中的Update_rows_event或Delete_rows_event必须携带完整的、可哈希的唯一键字段(即binlog_row_image=FULL),否则会 fallback 到前序算法 - 若表结构变更(如删主键、改唯一约束)、或应用层用了
binlog_row_image=MINIMAL,HASH_SCAN可能找不到匹配行,直接报错HA_ERR_KEY_NOT_FOUND (1032) - MySQL 官方选择默认不冒这个风险:宁可慢一点(
INDEX_SCAN),也不能同步中断
实际配置时哪些情况必须显式设置?
你不需要“开启”这个参数,但需要根据表结构和 binlog 配置决定是否追加 HASH_SCAN:
- 表有主键或非空唯一索引,且
binlog_row_image=FULL(默认) → 可安全加HASH_SCAN - 表无主键、无唯一索引 →
HASH_SCAN无效,只会 fallback 到TABLE_SCAN,甚至可能跳过它直接失败 - 使用了
binlog_row_image=MINIMAL或NOBLOB→HASH_SCAN失效,因为 before_image 缺失关键字段 - 从库启用了
slave_parallel_workers > 0→HASH_SCAN可显著降低 worker 间锁竞争,推荐启用
设置方式(动态生效,无需重启):
SET GLOBAL slave_rows_search_algorithms = 'TABLE_SCAN,INDEX_SCAN,HASH_SCAN';
注意:该变量只影响后续新启动的 SQL 线程(或并行 worker),已运行中的复制线程需 STOP SLAVE; START SLAVE; 才会重载。
容易踩的坑
- 直接执行
SET GLOBAL slave_rows_search_algorithms = 'HASH_SCAN';—— 错!这会覆盖默认策略,丢掉TABLE_SCAN和INDEX_SCAN作为保底,一旦哈希失败就彻底卡住 - 在 GTID 模式下修改后未检查
SHOW SLAVE STATUS\G中的Seconds_Behind_Master是否突增 ——HASH_SCAN加速效果明显,但若观察到延迟反而上升,说明哈希未命中,正在 fallback,需查表结构或 row_image 配置 - 忘记确认主库
binlog_row_image值:它必须是FULL(MySQL 5.7+ 默认),否则从库即使配了HASH_SCAN也用不上
HASH_SCAN 不是银弹,它是针对「无主键大表批量 DML 导致从库延迟爆炸」这一特定痛点的优化开关,不是所有主从环境都适合打开。真正关键的,是理解它依赖什么、失效时表现为何、以及 fallback 路径是否可靠。


















