在基于ROW模式复制的环境下,slave_rows_search_algorithms参数控制如何在行中搜索匹配项,特别是是否使用Hash Scan,设置后会立即对所有复制通道生效。其值可设置为INDEX_SCAN、TABLE_SCAN、HASH_SCAN中指定两个值,以逗号分隔,参数默认值为INDEX_SCAN,TABLE_SCAN。常见的推荐组合及其效果如下:

/*
Decision table:
- I --> Index scan / search
- T --> Table scan
- Hi --> Hash over index
- Ht --> Hash over the entire table
|--------------+-------+-----+-----+-----|
| Index\Option | I,T,H | I,T | I,H | T,H |
|--------------+-------+-----+-----+-----|
| PK / UK | I | I | I | Hi |
| K | Hi | I | Hi | Hi |
| No Index | Ht | I | Ht | Ht |
|--------------+-------+-----+-----+-----+
*/
  • 参数包含Index scan时,且有主键或唯一索引,使用Index scan
  • 参数包含Hash scan时,有主键索引或唯一索引,使用Index hash;如果没有,则使用entire table scan(Ht)
  • 参数包含Index scan时,如果有二级索引,使用Index scan;如果没有,则使用Table scan
  • 请勿使用TABLE_SCAN,HASH_SCAN,此设置强制对所有搜索都执行hash,它可能会导致record not found错误,或者单个事件包含对同一行的多个更新或依赖顺序的更新时出现重复键的错误
  • 参数可以指定单个值,但通常不建议,特别是单独设置INDEX_SCAN,如果没有索引的情况下会搜索不到行

Hash scan可以解决部分无主键表造成的复制延迟问题,提升从库回访效率,降低延迟。在应用rows events时,会将log_event中对行的更新缓存在m_hash和m_distinct_key_int中

  • m_hash:主要用于缓存更新的行记录的起始位置,结构为hash
  • m_distinct_key_list:如果有索引,则将索引值push到列表中,没有索引则不采用该列表

但Hash scan在部分场景下存在bug,可参考Bug #72788 HASH_SCAN seems broken: Can’t find record in ‘t1’ Error_code: 1032,其原因就在于m_distinct_key_list中的index key不是唯一的,存在对已经删除的记录重复删除的问题,造成同步报错Can’t find record。目前该BUG已在8.0.17中修复,但5.7并没有修复,只能自行添加主键或不采用hash scan来规避该问题。

参考链接:
MySQL无主键延迟优化(slave_rows_search_algorithms)