IO 等待导致 Mysql 提交期间速度严重下降(EXT4 JDB2 IO 为 99%)

IO 等待导致 Mysql 提交期间速度严重下降(EXT4 JDB2 IO 为 99%)

我正在使用 python 编写一个索引器,它索引文档并将其插入到数据库中,以前它是单一进程,但现在我将其改为多处理,运行 4 个并行进程。每次提取文本后,它都会插入数据库并执行提交。

现在遇到了 IO 问题,主要的 IO 问题不是我的进程,而是 EXT4 的 jdb2 日志系统。它处于 99.99% 的状态,导致 CPU 在每次 MySQL 提交时等待 IO。

我在网上看到很多人遇到这个问题,他们的解决方案是使用 barrier = 0 进行挂载。这会完全禁用日志功能吗?我的服务器有 UPS,我很想这么做,应该吗?

答案1

将数据库放在非日志文件系统中。至少大型服务器(oracle、sql server)有自己的日志功能(事务日志)并相应地优化其 IO。日志和数据库位于单独的文件系统和磁盘上,并依靠数据库内部功能来处理不良 IO。通常,除了写入日期之外,文件系统不会发生(较大的设置)更改,因为文件不会扩展 - 它们将以其“最终”大小生成(好的,管理员可以更改它),并且正如我所说,更改由数据库级事务日志跟踪。

您可能还想告诉我们您的硬件层是什么。大多数人都低估了这一点每秒输入/输出次数是数据库的限制因素,并认为小型磁盘组是大型数据库的合适环境。而我们中的一些人使用大量磁盘来处理数据库,因此可能支持更高的 IOPS。

答案2

弹性和性能之间总是存在权衡。

对于 ext4 上的 MySQL,barriers=1 默认值确实会导致速度变慢,但第一步操作不应该是禁用日志记录或打开 data=writeback。

首先,如果弹性非常重要,那么电池支持的 RAID 肯定是值得的。

我选择的安装选项(特别是在无电池支持的 RAID 上)是:

/dev/mapper/vg-mysql--data  /var/lib/mysql/data ext4  defaults,noatime,nodiratime,barrier=1,data=ordered  0 0

这是故意不使用 data=writeback 的,因为我不想冒文件系统损坏的风险,导致“崩溃和日志恢复后旧数据出现在文件中”(引用自man mount)。

my.cnf 中围绕 I/O 相关设置的完全弹性的理想配置是:

[mysqld]
sync_binlog = 1
innodb_flush_log_at_trx_commit = 1

我选择了以下权衡顺序来提高性能:

  1. sync_binlog = 0:这是我从完全弹性中更改的第一个 MySQL 配置。这样做的原因是它可以显著提高性能,尤其是在binlog_format=row(不幸的是 Jira 需要)的情况下。我在集群中使用了足够多的 MySQL 副本,如果 binlog 因断电情况而损坏,我会从另一个副本进行二进制复制。
  2. innodb_flush_log_at_trx_commit = 2:虽然完全符合 ACID 要求必须将值设为 1,但将值设为 2 时,“日志缓冲区会在每次提交时写入文件,但不会执行刷新到磁盘的操作。但是,当值为 2 时,日志文件也会每秒刷新一次。请注意,由于进程调度问题,每秒刷新一次并不能 100% 保证每秒都会发生。”(引自 MySQL 文档)
  3. 更新要使用的挂载选项data=writeback。请注意,如果这是您的根文件系统,您还需要传递内核命令行选项。我整理了几个步骤编码墙
  4. 测试各种值innodb_flush_method。O_DIRECT 被证明可以提高某些工作负载下的性能,但这不一定能在您的环境中发挥作用。
  5. 升级到 SSD,在这种情况下,您还需要增加,并调整设置,innodb_io_capacity例如innodb_adaptive_flushing、、、、和其他可能的设置。innodb_read_io_threadsinnodb_write_io_threadsinnodb_purge_threads

答案3

这是一个老问题,但我们上周在新的专用服务器上遇到了同样的问题(高 IO 等待,以及糟糕的插入/更新速度),这个解决方案直接解决了这个问题。

使用以下方式禁用日记功能tune2fs -O "^has_journal" /dev/<drive>是最快的解决方案,因为它消除了 JDB2 进程带来的 IO 等待。但是除非您有电池供电的驱动器,否则不建议这样做,因为一旦发生崩溃,您将丢失数据。如果您有doublewrite在 MySQL 中启用。但 .frm、日志等文件并不安全。我们尝试将这些文件移至另一个驱动器(尤其是 bin 日志),但 jdb2 IO 等待仍然存在。所以这让我们很不舒服。

data=writeback,relatime,nobarrier并不能像禁用整个分区的日志功能那样加快写入/读取速度。ext4 的更多选项位于EXT4 文档

我们案件的真正罪魁祸首是sync_binlog。我们已经设置了,1并且/etc/mysql/my.cnf它是杀害表现。

Percona 在这里验证了这一点。我们将其设置为默认值0,性能提高了 500% 以上。

答案4

您使用什么数据库引擎来插入这些数据?

如果是 MyISAM:则必须在写入期间锁定整个表,因此运行并发插入线程将会杀死任何系统,无论系统功能多么强大。

确保这些表使用的是 InnoDB。

相关内容