作者:PawełAndruszkiewicz 译:徐轶韬
MySQL Shell 8.0.21带有两个实用程序,可用于对实例(util.dumpInstance()
)或选定的模式(util.dumpSchemas()
)执行逻辑转储。这些工具相对于mysqldump
实用程序提供了重大的性能改进,我们的一些基准测试显示吞吐量高达3GB / s!让我们看看如何实现这一目标。
这是有关MySQL Shell Dump&Load的博客文章系列的第4部分
转储过程使用多个线程来执行任务(可以使用threads
选项指定线程数),从而允许并行执行耗时的操作。每个线程都开启自己与目标服务器的连接,可以进行转储数据,转储DDL或将表数据拆分为大块的工作。
当consistent
选项设置为true
(默认值)时,转储将保持一致(转储的表使用InnoDB引擎)。启动转储过程时,全局Shell会话将使用 FLUSH TABLES WITH READ LOCK
设置全局读取锁,接下来,所有线程都与服务器建立连接并使用以下命令开始事务:
SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ
START TRANSACTION WITH CONSISTENT SNAPSHOT
一旦所有线程开始事务,该实例将被锁定以进行备份并释放全局读取锁。
通常情况下,模式中表的大小会有很大差异,有一些非常大的表,也有许多较小的表。在这种情况下,添加更多线程将不会加快转储过程。为了克服此问题,可以将表中的数据划分为较小的块,每个块将通过一个线程转储到单独的文件中。
我们的分块算法致力于找到将表划分为大致相等大小的块的主键(或唯一索引)。它使用EXPLAIN
语句来确定块大小,从优化器中获取行数估计,而不是例如SELECT COUNT(*)
需要逐行扫描行的估计。这些估计值通常不是很准确,但是对于我们的目的而言,它明显更快且足够好。
默认情况下,分块处于打开状态,会导致文件包含大约32MB的未压缩数据。可以分别使用chunking
和bytesPerChunk
选项来设置这些功能,如果您的数据集很大,通常最好增加后者。
mysqldump、mysqlpump
和mydumper
写入数据为一系列的INSERT
语句,而新的Shell工具使用LOAD DATA的默认格式
。输出文件平均较小,这意味着可以更快地生成它们。另一个好处是,加载此类文件要快得多。
默认情况下,所有数据文件都使用zstd
算法压缩,从而在压缩率和编码性能之间取得了良好的平衡。另一种支持的算法是gzip
。也可以通过将compression
选项设置为none来禁用压缩
。
代码已经过严格的基准测试。在此过程中,我们确定并修复了整个Shell代码库中的各种问题,例如不必要的数据副本,冗余函数调用,多余的虚拟调用。已经将将数据写入输出文件的功能进行了仔细的分析和优化。
下面是Shell的两个新应用程序与mysqldump
,mysqlpump
以及mydumper进行的性能比较
:
有关更多基准测试结果,请参见MySQL Shell Dump&Load第2部分:基准测试
util.dumpInstance()
和util.dumpSchemas()
在目前提供一些重大的性能提升,但仍有一定的提升空间。特别是,我们的分块算法肯定可以优化,这是我们计划将来解决的问题。敬请关注!