MySQL存储引擎之Spider内核深度解析(3)
图8-1. 索引扫描实现 图8-2. 全表扫描 2、INSERT操作MySQL的handler类对于INSERT操作提供的接口函数的名字是write_row.存储引擎想要支持INSERT操作就必须实现write_row方法.Spider对于write_row方法的实现是简单地根据查询解析的信息拼接一条INSERT语句,发往后端节点处理.如果是批量插入操作则需要与MySQL Server层配合,将INSERT语句批量发到后端节点. 图9结合一条批量插入的INSERT语句给出MySQL中INSERT操作的具体实现. mysql_insert调用write_row执行具体的插入操作(第8行).这是存储引擎必须实现的方法.对应于spider,spider根据查询涉及到的列(field)拼成一条INSERT语句(如果是分片数据库,VALUSE中的列必须包含分区键,分区键是自增列的情况除外).图9中的QUERY将用户ID(ID)和用户名(Name)插入到user表,其中ID是分区键.mysql_insert根据VALUES包含的元组数目,判断是否需要进行批量插入操作.该例子的QUERY的VALUES包含4条元组,所有需要进行批量插入操作.MySQL循环调用write_row方法触发spider生成INSERT语句.Spider的write_row方法实现中会根据分区键将INSERT语句进行分组(第5行~第9行).图9给出的实例只有两个数据分片,所以SQL语句被分成两组.处理完VALUES以后,Spider的INSERT语句也拼接完成. ha_end_bulk_insert方法通知Spider完成VALUES处理.此时,Spider将INSERT发送到后端节点进行处理(第11行). 图9. Spider中INSERT操作的实现 3、DELETE实现Spider想要支持DELETE操作必须实现MySQL handler类提供的ha_delete_row方法.与INSERT操作不同,DELETE操作需要生成一条SELECT语句将查询涉及的分区键拉到Spider节点.这是因为MySQL Server层的“once-a-tuple”的查询执行模型(实际上基本所有的关系数据库系统都采用该模型)会驱动Spider逐个拼接DELETE语句,然后发往后端节点.这时候,Spider需要知道对应的DELETE语句该往哪个后端节点发送.为了减少网络开销,Spider提供了批量发送DELETE语句的功能. 图10. DELETE实现 图10给出了Spiderpider中delete的实现.MySQL Server层首先确定表的访问方法:采用索引扫描或者全部扫描(第5行)?DELETE方法需要执行一次查找操作,调用get_next方法(info.read_record)获取一条元组(第10行).Spider需要判断是否第一次调用get_next方法.如果是的话,则需要生成SELECT语句,将数据节点的数据拉到本地.否则,Spider直接从本地返回数据给上层调用者.接下来,Server层调用ha_delete_row方法将数据删除.这是存储引擎需要具体实现的方法.由于Spider本身并不存储数据的缘故,其实现delete操作主要思想是利用从后端节点拉取过来的数据(分区键,过滤条件等),拼接成一条DELETE语句.然后,发送该请求到数据节点.Spider为了优化网络开销,提供了批量发送DELETE语句的选项. UPDATE操作的实现类似DELETE,都需要Spider生成SELECT语句从后端节点拉取数据.只不过,UPDATE在更新区分键的时候,可能需要多一次DELETE操作(删除原来分区的数据,将新的数据插入到不同的分区). 总结Spider的最大亮点是为MySQL的使用者提供分库分表的中间件解决方案,同时在SQL语法上兼容MySQL.这得益于Spider作为MySQL的插拔式引擎而存在.Spider是一个proxy,其本身并没有存储数据,因此上层的读写表请求需要转换成SQL语句,重新路由到后端的数据节点.相比其它的中间件解决方案,Spider的查询解析次数都是两次,并没有过多开销.此外,Spider还针对聚集、排序等操作提供了MAP REDUCE的解决方案. 总之,从兼容性、性能上衡量,Spider是MySQL分库分表一个不错的选项. 文章来自微信公众号:DBAplus社群 (编辑:ASP站长网) |