相对于 MySQL 官方提供的逻辑备份工具 mysqldump,mydumper 最突出的特性就是可采用多线程并行备份,极大提高了数据导出的速度。本文基于 mydumper在 github 上托管的最新源码,对其实现原理进行较详细的介绍。
与其他备份工具一样,mydumper 默认情况下是用 FTWRL (Flush Tables With Read Lock) 全局读锁来保证备份数据的一致性。FTWRL 锁对 MySQL 的杀伤力很大,特别是在读写负载比较高的场景,因而mydumper在加锁时会优先使用影响更小的备份锁,依次执行 LOCK TABLES FOR BACKUP和LOCK TABLES FOR BINLOG,如果导出实例支持的话。
在进行数据备份时,mydumper 的主逻辑由一个主线程和多个备份子线程共同完成,默认情况下为四个子线程。其主线程的主要流程为:
FLUSH TABLES WITH READ LOCK 将脏页刷新到磁盘并获得只读锁START TRANSACTION /!40108 WITH CONSISTENT SNAPSHOT /开启事务并获取一致性快照SHOW MASTER STATUS 获得binlog位点信息queue中UNLOCK TABLES / FTWRL / 释放锁备份子线程的主要流程是:
START TRANSACTION /!40108 WITH CONSISTENT SNAPSHOT /开启事务并获取一致性快照值得注意的是,虽然 mydumper 支持表级别的并行操作,且在导出的时候会对大的表数据进行分块 chunk 导出,但是同一个表的 chunks 是在同一个线程中处理的,并非多线程并行的。
mydumper执行备份的详细流程如下

流程图中的步骤基本与源码中的函数名称对应,可以将源码与流程图对照来看。
如流程图中所示,主线程会在开始时获取 FTWRL 全局只读锁,来保证确保接下来没有变更产生。
之后开启一致性读事务,创建子线程并确认子线程 session 隔离级别为 Repeatable Read、开启一致性读事务。这样保证了即使主线程在所有导出任务结束之前释放锁,子线程在处理 InnoDB 表时能利用 MySQL MVCC 特性继续执行,得到事务开启时间点的一致性数据视图。
接下来主线程会在自己的 session 里面读取数据库表结构、拆分任务,主线程UNLOCK TABLES释放锁由非 InnoDB 表都处理完的事件来触发,确保所有的非事务表的数据一致性。
mydumper通过结合以上逻辑可以保证即使在多线程处理的情形下,备份数据仍是一致的。
这个选项与 mysqldump 的--single-transaction功能类似,将备份流程当作一个大事务来处理,可以看到流程中在主线程等待子线程创建完之后,主线程就会提前UNLOCK TABLES释放锁了。
显然,这个时候无法保证非InnoDB表的数据一致性,这是因为MyISAM等非事务并不支持MVCC特性,无法实现一致性快照读。
mydumper有一个比较有意思的--less-locking选项,主要目的就是尽量减少 mydumper 中FTWRL整体的锁定时间。
这种模式的实现比较巧妙,在这种模式下,线程数量是用户指定线程数n的两倍,默认情况下也即是八个线程,新增的线程为专门处理非 InnoDB 表的一组线程less_locking_threads。主要的流程为:
FLUSH TABLES WITH READ LOCK 获取全局只读锁START TRANSACTION /!40108 WITH CONSISTENT SNAPSHOT / 开启事务并获取一致性快照SHOW MASTER STATUS获得binlog位点信息threads会条件等待less_locking_threads结束才开始工作,less_locking_threads中结束一个就通知threads中的一个线程开始工作,其他表的导出任务还是按照原来的流程处理push到队列queue`中less_locking_threads中每个线程会拿到一个非InnoDB表任务执行,直到执行完通知threads中的一个线程开始执行queue中的任务less_locking_threads执行完时,主线程UNLOCK TABLES / FTWRL / 释放锁可以看到在--less-locking模式下,mydumper 会首先集中能力处理完所有非 InnoDB 表的任务,尽快满足主线程释放锁的条件。由于每个less_locking_threads处理的任务量相当,这基本是最快的处理方式了。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。