从库数据查找和参数slave_rows_search_alg

本节我们假定参数binlog_row_image设置为“全部”也就是默认值。

一、从一个列子出发

在开始之前我们先假定参数“slave_rows_search_algorithms”为默认值,即:

TABLE_SCAN, INDEX_SCAN

因为这个参数会直接影响到对索引的利用方式。

我们还是以“删除”操作为例,实际上对于索引的选择“更新”操作也是一样的,因为都是通过before_image去查找数据。我测试的表结构,数据和操作如下:

mysql>显示创建表tkkk \ G

* * * * * * * * * * * * * * * * * * * * * * * * * * * 1。行* * * * * * * * * * * * * * * * * * * * * * * * * * *

表:tkkk

创建表:创建表“tkkk”(

' a ' int(11)默认为空,

" b " int(11)默认为空,

' c ' int(11)默认为空,

键' a ' (' a ')

)引擎=InnoDB默认字符集=utf8

1行组(0.00秒)

mysql>select * from tkkk;

+ + - - - - - - - - - - - - - - - - - - +

| | | b c |

+ - - - - - - - - - - - - - - - - - - + +

| 1 | 1 | 1 |

| 2 | 2 | 2 |

| 3 | 3 | 3 |

| 4 | 4 | 4 |

| 5 | 5 | 5 |

| 6 | 6 | 6 |

| 7 | 7 | 7 |

| 8 8 8 | | |

| 9 | 9 | 9 |

| 10 | | 10 |

| 11 | 11 | 11 |

| 12 12 | | 12 |

| 13 | 13 | 13 |

15 15 15 | | | |

15 | 16 | | |

15 | | 17 | 17 |

+ - - - - - - - - - - - - - - - - - - + +

16行组(2.21秒)

mysql>delete from tkkk where a=15;

  Query OK, 3 rows affected (6.24 sec)

  因为我做了debug索引这里时间看起来很长

  对于这样一个‘Delete’语句来讲主库会利用到索引 KEY a,删除的三条数据我们实际上只需要一次索引的定位(参考btr_cur_search_to_nth_level函数),然后顺序扫描接下来的数据进行删除就可以了。大概的流程如下图:

  

从库数据查找和参数slave_rows_search_alg


  这条数据删除的三条数据的before_image将会记录到一个DELETE_ROWS_EVENT中。从库应用的时候会重新评估应该使用哪个索引,优先使用主键和唯一键。对于Event中的每条数据都需要进行索引定位操作,并且对于非唯一索引来讲第一次返回的第一行数据可能并不是删除的数据,还需要需要继续扫描下一行,在函数Rows_log_event::do_index_scan_and_update中有如下代码:

  while (record_compare(m_table, &m_cols))//比较每一个字段 如果不相等 扫描下一行

  {

  while((error=next_record_scan(false)))//扫描下一行

  {

/* We just skip records that has already been deleted */

  if (error==HA_ERR_RECORD_DELETED)

  continue;

  DBUG_PRINT("info",("no record matching the given row found"));

  goto end;

  }

  }

  这些代价是比主库更大的。在这个列子中没有主键和唯一键,因此依旧使用的是索引KEY a,大概流程如下图:

  

从库数据查找和参数slave_rows_search_alg


  但是如果我们在从库增加一个主键,那么在从库进行应用的时候流程如下:

  

从库数据查找和参数slave_rows_search_alg


  我们从上面的流程来看,主库‘Delete’操作和从库‘Delete’操作主要的区别在于:

  从库每条数据都需要索引定位查找数据。

  从库在某些情况下通过非唯一索引查找的数据第一条数据可能并不是删除的数据,因此还需要继续进行索引定位和查找。

  对于主库来讲一般只需要一次数据定位查找即可,接下来访问下一条数据就好了。其实对于真正的删除操作来讲并没有太多的区别。如果合理的使用了主键和唯一键可以将上面提到的两点影响降低。在造成从库延迟的情况中,没有合理的使用主键和唯一键是一个比较重要的原因。

  最后如果表上一个索引都没有的话,那么情况变得更加严重,简单的图如下:

  

从库数据查找和参数slave_rows_search_alg


  我们可以看到每一行数据的更改都需要进行全表扫描,这种问题就非常严重了。这种情况使用参数‘slave_rows_search_algorithms’的HASH_SCAN选项也许可以提高性能,下面我们就来进行讨论。

从库数据查找和参数slave_rows_search_alg