年前看到percona的blog关于mydumper的lockless更新,因此萌发了重写mydumper的想法。这篇文章是我对mydumper的分析,以及对之前重写的产品datapumper的思考与实践。在MySQL的逻辑备份中,mydumper逻辑备份一直以并发和快速著称。mydumper为什么快 ?我们简单的描述下mydumper的设计实现。为简单起见,我用一张图来简单描述下设计原理(以mydumper 0.9.1版本,开启less-locking 为列):
关键点:
1.dump 完No-Innodb 以后,锁就可以解开了,因为所有的事物都在flush tables with read lock 以后打开,所以所有的子线程和主线程看到的都是锁住之后的数据,没有新的数据进来。所有的线程看到了一致的数据。
2.由于dump Innodb 的任务,都是由主线程将表进行分解为多个chunk,所以主线程在分解为chunk的时候看到的数据,和任务被多线程执行产出的数据是一致的。
比如: 主线程产生 select c1,c2,c3 from t1 where id>=1 and id<10001 和子线程执行这个sql所对应的数据是一致的。
问题:
1.全局锁在所有的No-Innodb tables 锁住之后就解开了,相对之前的版本(非less locking),锁持有的时间更短了,但还是持有全局锁。
2.导出需要先导出到文件,然后用myloader到目标库。
改进点:
1.位置信息获取,无需全局锁,通过主线程以RR(repeat read)开启事物后,通过Binlog_snapshot_file/Binlog_snapshot_position获取。
2.所有子线程无需全局锁,可以看到一致的数据(percona支持 START TRANSACTION WITH CONSISTENT SNAPSHOT FROM SESSION session_id)。
例如:A连接开启事物,则B可以克隆A的事物,并看到和A相同的内容,C可以克隆B或者A的事物,并看到和A一样的内容。(这里的session_id为连接的id,及processlist 输出的ID)。
3.去掉文件,直接将产生的sql输出的消费队列,队列另一端,consumer 并发的导入即可。
所以我在此基础上开发了datapumper,数据无需落地,不许要全局锁,所有的线程就可以得到coordinate position(所有的线程看到的都是同一份数据)。
因此我设计的data pumper 改进如下:
因此我设计的data pumper 改进如下:
由于只针对了Innodb表的导出,所以无需关心no-innodb tables的一致性。当然,如果需要加入no-innodb tables也很简单,只需要先lock no-innodb tables,然后进行no-innodb tables 的导出,导出完之后,释放锁。