更新时间:2023-08-28
在下面,您可以找到有关将数据加载到 MySQL 中的其他技术信息。此信息面向熟悉 MySQL 服务器架构的高级用户。
二进制日志
与关闭二进制日志记录后加载相同数据的情况相比,启用二进制日志记录后加载数据会导致性能损失,并需要额外的可用磁盘空间 (高达四倍以上)。性能损失的严重程度和所需的可用磁盘空间量与加载数据所使用的事务大小成正比。
事务大小
事务大小在 MySQL 数据加载中起着重要的作用。它对资源消耗、磁盘空间使用率、恢复过程、恢复时间和 输入格式 (平面文件或 SQL) 有重大影响。本部分介绍了事务大小如何影响二进制日志记录以及让案例在大数 据加载过程中禁用二进制日志记录。如前文所述,通过设置 RDS 自动备份保留期,可启用和禁用二 进制日志记录。非零值会启用二进制日志记录,零会将其禁用。我们还介绍了大型事务对 InnoDB 的影响以 及将事务大小保持在较小状态的重要性。
小型事务
对于小型事务,二进制日志记录会使加载数据所需的磁盘写入次数翻倍。这种影响会严重降低其他数据库会 话的性能,并增加数据加载所需的时间。体验到的降级部分取决于上传速率、加载期间发生的其他数据库活 动以及 RDS 数据库实例的容量。
此外,二进制日志占用的磁盘空间大致等于数据备份和删除前加载的数据量。幸好 RDS 会频繁备份 并删除二进制日志,以尽量减少这种情况。
大型事务
大型事务对启用二进制日志记录的 IOPS 和磁盘占用量的不良影响可达 3 倍。这是因为二进制日志缓存会溢 到磁盘,占用磁盘空间并会为每次写入增加额外 IO。事务提交或回滚前,无法将缓存写入二进制日志,因此,其会根据数据加载量按比例占用磁盘空间。提交事务后,必须将缓存复制到二进制日志,为磁盘上的数 据创建第三副本。
因此,启用二进制日志记录后加载数据所使用的可用磁盘空间必须至少为禁用二进制日志记录加载过程的三 倍。例如,在加载过程中,作为单个事务加载的 10 GiB 数据将至少占用 30 GiB 磁盘空间。它使用表的 10
GiB + 二进制日志缓存的 10 GiB + 二进制日志本身的 10 GiB。缓存文件会一直保存在磁盘上,直至创建缓存 文件的会话终止或在另一事务处理期间会话再次填充其二进制日志缓存。备份前二进制日志必须保存在磁盘 上,因此可能要过一段时间才会释放额外的 20 GiB 空间。
在使用 LOAD DATA LOCAL INFILE 加载数据的情况下,如果数据库必须从加载前创建的备份中恢复,请为 数据创建另一个副本。在恢复期间,MySQL 将二进制日志中的数据提取到平面文件中。然后,MySQL 执行 LOAD DATA LOCAL INFILE,就如在原始事务中一样。不过,这次输入文件位于数据库服务器本地。继续上 述示例,除非可以使用的可用磁盘空间至少达到 40 GiB,否则恢复将失败。
禁用二进制日志记录
在可能的情况下,在大数据加载过程中禁用二进制日志记录,以避免资源开销和增加磁盘空间要求。在 RDS 中,只需将备份保留期设置为零就可以禁用二进制日志记录。如果您这样做,我们建议您先制 作数据库实例的数据库快照,接着再加载。这样,在需要的情况下,可快速轻松地撤消在加载期间进行的更 改。
加载后,将备份保留期设置回相应 (非零) 值。 如果数据库实例是只读副本的源数据库实例,您就无法将备份保留期设置为零。
InnoDB
本部分中的信息为使用 InnoDB 时保持小型事务提供了有力论据。
撤消
InnoDB 可以生成撤消以支持事务回滚和 MVCC 等功能。撤消可存储在 InnoDB 系统表空间 (通常为 ibdata1) 中,并且在清除线程删除前会一直保留。清除线程无法超越最早的活动事务撤消,因此,直到此事务提交或 完成回滚后才能有效地阻止此线程。如果在加载期间数据库正在处理其他事务,则其撤消同样会在系统表空 间中累计并且无法删除,即使它们已提交并且其他事务不需要撤消 MVCC。在这种情况下,访问由任一事务 (不仅仅是负载事务) 更改的任一行的所有事务 (包括只读事务) 都会减速。之所以减速,是因为它们会通过撤 消进行扫描,而这些撤消如果不适用于长期运行的负载事务,就可能会被清除。
撤消数据存储在系统表空间中,并且系统表空间大小从不收缩。因此,大数据负载事务可能会导致系统表空 间变得很大,如果不从头开始重新创建数据库,这些占用的磁盘空间就无法回收。
回滚
InnoDB 已针对提交进行了优化。回滚大型事务可能需要很长时间。在某些情况下,执行时间点恢复或还原 数据库快照可能会更快。
输入数据格式
MySQL 可以接受以下两种传入数据格式之一:平面文件和 SQL。本部分说明了每一种格式的一些主要优势 和劣势。
平面文件
只要将事务保持在相对较小的状态,使用 LOAD DATA LOCAL INFILE 加载平面文件就是最快速、最经济的 数据加载方式。由于减少了数据库中的开销,因而与使用 SQL 加载相同的数据相比,平面文件需要的网络流 量通常更少、传输成本更低并且加载速度快得多。
一个大事务
LOAD DATA LOCAL INFILE 会将整个平面文件作为一个事务进行加载。这不一定是一件坏事。如果可以将 单个文件大小保持在较小状态,会有很多优势:
• 恢复功能 – 跟踪已加载的文件非常轻松。如果在加载期间出现问题,只需简要操作就可以从停止处继续加 载。可能要将一些数据重新传送到 RDS,但使用小文件,就可以将重新传输的量减少至最低水 平。
• 并行加载数据 – 如果 IOPS 和网络带宽足以支持单一文件的加载,那么并行加载就可以节省时间。
• 限制加载速率 – 数据加载是否影响其他进程? 通过增加文件之间的时间间隔限制负载。
注意
LOAD DATA LOCAL INFILE 的优势会随着事务大小的增加而迅速减弱。如果无法将一个大数据集分成几个 较小的数据集,SQL 可能是更好的选择。
SQL
与平面文件相比,SQL 的一个主要优势为:易于将事务大小保持在较小状态。不过,SQL 的加载时间显著 长于平面文件,并且在发生故障后,难以确定加载恢复点。例如,Mysqldump 文件不可重新启动。如果加载 Mysqldump 文件时出现故障,需要在加载恢复前修改或替换该文件。另一种方法是在纠正故障的原因后,还 原到加载前的时间点,然后回放此文件。
减少加载时间
这里有一些可以减少加载时间的其他技巧:
• 加载前创建所有辅助索引。对于熟悉其他数据库的人而言,这样做违反常规。添加或修改辅助索引会使 MySQL 创建一个指数发生变化的新表,将数据从现有表复制到新表并删掉原始表。
• 以 PK 顺序加载数据。这对 InnoDB 表尤为有用,其中加载时间可减少 75% 到 80%,数据文件大小可减小 一半。
• 禁用外键约束 foreign_key_checks=0。对于使用 LOAD DATA LOCAL INFILE 加载的平面文件,在很多情 况下都需要这一操作。对于任何加载过程,禁用 FK 检查都会提供显著的性能收益。请务必确保启用约束 并验证加载后的数据。
• 并行加载,除非已经接近资源限制。适当时使用分区表。
• 加载时,通过 SQL 使用多值插入,将语句的执行开销降到最低。使用 Mysqldump 时,这会自动完成。
• 减少 InnoDB 日志 IO innodb_flush_log_at_trx_commit=0
• 如果您要将数据加载到没有只读副本的数据库实例,请在加载数据时将 sync_binlog 参数设置为 0。数据 加载完毕后,将 sync_binlog 参数设置回 1。
• 在将数据库实例转换为多资源池部署之前加载数据。不过,如果数据库实例已经使用多资源池部署,则不 建议切换为单资源池部署来加载数据,因为这样做只能提高利润。
注意⚠️:
使用 innodb_flush_log_at_trx_commit=0 会导致 InnoDB 每秒都刷新其日志,而不是在每次提交时刷 新。这提供了很大的速度优势,但在崩溃期间可能导致数据丢失。请谨慎使用。