作者:Alfredo Kojima 译:徐轶韬
这是有关MySQL Shell转储和加载的博客文章系列的第3部分
MySQL Shell转储和加载实用程序是MySQL Shell 8.0.21提供的新工具,其主要目标是尽量减少创建和恢复大型数据集的逻辑转储所需的时间。
通过大量并行化技术及其他技术,我们能够将这些任务所需的时间减少一个数量级(与以前的转储实用程序相比较)。
实际上,在使用大型数据集的基准测试中,我们观察到转储速度接近3 GB / s,加载超过 200MB / s。可以在本系列的第2部分中了解有关此工具的更多信息以及与其他类似工具的性能比较。
在本文中,我将重点介绍加载程序的实现方法。您可以在第4部分中了解到在转储程序中所做的工作,转储程序的性能要比加载程序大得多。
在许多情况下,数据加载期间的瓶颈是InnoDB的重做日志或二进制日志。在逻辑加载期间,通常禁用二进制日志(loadDump()
has skipBinlog: true
)。现在还 可以在MySQL Server 8.0.21中禁用InnoDB重做日志。
使用 ALTER INSTANCE DISABLE INNODB REDO_LOG
,可以禁用重做日志和双写,这可以提高吞吐量并减少磁盘上的写入增加。请注意,MySQL Shell loadDump()
不会禁用重做日志,必须在加载数据之前手动执行此操作。
尽快将数据移出和移回MySQL的关键是在多个并行会话/线程之间分配工作。
事实上 mysqlpump 已经做到了并行处理,但是它的粒度限制为每个表一个线程(仅适用于转储,加载是单线程的)。如果您的大多数表的大小都差不多,那会很好。但是,这种情况很少见,您经常会遇到一个线程转储1或2个巨大的表,而其他线程都已完成并处于空闲状态的情况。它还将转储到单个SQL文件,从而创建一个序列化点。单个SQL文件还使得并行加载所有数据变得更加困难,因为除了在脚本中找到合适的边界用于线程之间划分工作之外,还必须解析该文件。
Shell使用一种更具攻击性的方法,即在转储过程中将表分成小块,这些小块存储在单独的文件中。即使在单个表上工作时,我们也可以并行化,并且加载适,无需担心会拆分文件。
mydumper 也将表分解为较小的块,但是它每一次只加载同一表的块。尽管比在单个线程中加载整个表要快,但这种方法并不能像使用Shell一样扩展,我们通过谨慎地调度块来最大程度地提高摄取率,这将在本文后面的内容中进行解释。
在下面的图形中,我们表示每种方法的效率差异:
MySQL Shell具有的其他显着功能:
与mysqldump,mysqlpump产生的转储不同,Shell转储将DDL,数据和元数据写入单独的文件。表也细分为大块,并写入多个类似CSV的文件中。
这可能会有一些缺点,因为转储不可以方便地复制的单个文件。但是,有几个优点:
LOAD DATA LOCAL INFILE
而不是普通SQL INSERT
语句的格式转储。即使是单线程加载,减少的解析量也应意味着性能至少要好一些。要最大化MySQL的加载性能,仅在客户端并行化工作是不够的。我们还需要通过最佳方式的调整和排序工作来帮助MySQL服务器,使其尽可能快地获取数据。
为此,加载程序执行以下操作:
更快地加载表的一种常见做法是推迟创建二级索引。也就是说,在创建表时剥离二级索引,加载数据然后才创建索引。
在我们的测试中,我们发现,除了一种例外,推迟表索引通常无济于事,甚至可能适得其反。延迟索引是否有所帮助取决于您的具体情况,因此我们建议尝试使用deferTableIndexes
选项。
设置deferTableIndexes
为all的好处之一是辅助索引的碎片化程度降低,可能占用更少的磁盘空间。
但是,在推迟全文索引时,我们看到了加载时间的持续改进。因此,deferTableIndexes
默认为fulltext
。设置为all
会推迟所有表的所有索引。
通过重新设计逻辑转储,与以前的工具相比,我们能够获得显着的性能改进。在许多情况下,即使是功能最强大的硬件,过去耗时数小时甚至全天的转储现在都可以在不到一个小时甚至不到几分钟的时间内完成。
同样重要的是,通过加载这些转储还原服务器也要快得多。与加载等效的.sql
转储文件相比,从Shell转储中还原大型数据库仅需花费一小部分时间。当需要紧急恢复时,这可以释放一些宝贵的时间!
我们希望您会尝试我们的新实用程序,并且发现它们不仅速度快,而且功能强大且易于使用。