#### 17.5.1.27 复制和行搜索

当使用基于行的复制格式的副本应用[`更新`](update.html)要么[`删除`](delete.html)操作时，它必须在相关表中搜索匹配的行。用于执行此过程的算法使用表的一个索引作为首选执行搜索，如果没有合适的索引，则使用哈希表。

该算法首先评估表定义中的可用索引，以查看是否有任何合适的索引可以使用，如果有多种可能性，哪个索引最适合该操作。该算法忽略以下类型的索引：

-   全文索引。

-   隐藏索引。

-   生成的索引。

-   多值索引。

-   行事件的前映像不包含索引的所有列的任何索引。

    如果排除这些索引类型后没有合适的索引，则算法不会使用索引进行搜索。如果有合适的索引，则从候选索引中选出一个，按以下优先顺序排列：

1.  一个主键。

2.  一个唯一索引，其中索引中的每一列都有一个 NOT NULL 属性。如果有多个这样的索引可用，算法会选择这些索引中最左边的。

3.  任何其他索引。如果有多个这样的索引可用，算法会选择这些索引中最左边的。

    如果算法能够选择主键或唯一索引，其中索引中的每一列都有一个`非空`属性，它使用这个索引来遍历[`更新`](update.html)要么[`删除`](delete.html)手术。对于行事件中的每一行，算法都会在索引中查找该行以定位要更新的表记录。如果没有找到匹配的记录，则返回错误 ER\_钥匙\_不是\_找到并停止复制应用程序线程。

    如果算法无法找到合适的索引，或者只能找到非唯一索引或包含空值的索引，则使用哈希表来帮助识别表记录。该算法创建一个哈希表，其中包含[`更新`](update.html)要么[`删除`](delete.html)操作，键作为行的完整前像。然后，该算法迭代目标表中的所有记录，如果找到，则使用选定的索引，否则执行全表扫描。对于目标表中的每条记录，它确定该行是否存在于哈希表中。如果在哈希表中找到该行，则更新目标表中的记录，并从哈希表中删除该行。当目标表中的所有记录都检查完毕后，算法会验证哈希表现在是否为空。如果哈希表中还有任何不匹配的行，算法将返回错误 ER\_钥匙\_不是\_找到并停止复制应用程序线程。

    这[`slave_rows_search_algorithms`](replication-options-replica.html#sysvar_slave_rows_search_algorithms)系统变量以前用于控制如何在行中搜索匹配项。现在不推荐使用此系统变量，因为默认设置（使用索引扫描后跟如上所述的哈希扫描）对于性能而言是最佳的，并且在所有情况下都能正常工作。
