MySQL 大磁盘 activity 即使没有查询 运行

MySQL heavy disk activity even with no queries running

正在尝试解决由 MySQL 引起的神秘磁盘 io 瓶颈问题。

我正在使用以下命令来测试磁盘 read/write 速度:

#write
dd if=/dev/zero of=/tmp/writetest bs=1M count=1024 conv=fdatasync,notrunc

#read
echo 3 > /proc/sys/vm/drop_caches; dd if=/tmp/writetest of=/dev/null bs=1M count=1024

我重新启动了机器,禁用了 cron,所以 none 我的常用进程是 运行ning 查询,终止了通常 运行s 的 Web 服务器,并终止了 mysqld。

当我 运行 没有 mysqld 运行ning 的读取测试时,我得到 1073741824 bytes (1.1 GB) copied, 2.19439 s, 489 MB/s。一直在 450-500 左右 MB/s.

当我开始备份 mysql 服务,然后再次 运行 读取测试时,我得到 1073741824 bytes (1.1 GB) copied, 135.657 s, 7.9 MB/s。一直在 5MB/s.

左右

运行 show full processlist in mysql 不显示任何查询(而且我禁用了所有 运行ning 查询)。在 MySQLWorkbench 的服务器状态选项卡中,我可以看到 InnoDB 读取在每秒 30-200 次读取和每秒 3-15 次写入之间波动,即使没有查询 运行ning 也是如此。

如果我 运行 iotop -oPa 我可以看到 mysqld 在没有查询 运行ning 时每秒读取 1MB 磁盘。考虑到没有查询是 运行ning,这似乎很多,但与此同时,这似乎不足以导致我的 dd 命令花费这么长时间......唯一执行磁盘的其他事情io 是 jbd2/sda3-8.

不确定是否相关,但如果我尝试使用 service mysql stop 终止 mysql 服务器,它会显示 "Attempt to stop MySQL timed out",并且 mysqld 进程继续 运行ning,但我无法再连接到数据库。我必须使用 kill -9 终止 mysqld 进程并重新启动服务器。

这一切似乎都是出乎意料的。这台服务器几个月来一直在进行繁重的日志解析、大量插入和选择,直到上周末我们开始看到这个磁盘 io 瓶颈。

我如何找出为什么 MySQL 在本质上空闲时进行如此多的磁盘读取?

你 update/delete/insert 行数很大吗?如果是这样,请考虑写入磁盘的这些“延迟”:

  • 包含数据的块不会立即写回磁盘。
  • UNIQUE 键同上。
  • 二级索引的更新进入“更改缓冲区”,它们被折叠到索引块中,通常甚至更晚。
  • Updates/deletes留下一个交易完成后需要清理的“历史列表”

这些事情由 PROCESSLIST 中没有显示的后台任务处理。它们可能在 mysqld 进程中可见,主要是 I/O。 (CPU 可能很少。)

ROLLBACK吗?交易“乐观”。因此 ROLLBACK 必须做很多工作才能“撤消”乐观地已经提交的内容。

如果你突然杀掉mysqld(或关闭电源),那么ROLLBACK会在重启后发生。

SSD 没有“寻道”时间。 HDD 必须将 read/write 个磁头移动一个可变的量;这需要时间。如果您的 dd 在磁盘的一端工作,而 mysqld 在另一端工作,则“搜索”会增加明显的 I/O 时间。

事实证明,与许多性能问题一样,这是一个多方面的问题。

基本上问题出在夜间系统和数据库备份写入单独的 HDD raid 阵列 运行 到第二天,然后主发送 FLUSH TABLES 并导致 mysql 作业和复制工作等待。此外,一个不必要的副进程每天在系统中复制数 GB 的文本文件数次。大量的上下文切换,因为系统试图复制备份数据,同时还执行 mysql 工作(复制和其他作业)。

我最终减少了我们正在复制的表的数量(有些是不必要的),减少了不需要时在系统周围复制文本文件,增加分配给 mysql 服务器的内存和 io,简化mysql 备份和系统备份,并限制 cron 作业 运行 宁 mysql 进程给 mysql 备份更多的时间来完成。综上所述,每天早上 7 点备份才勉强完成,所以我最终决定我们只需要在周末而不是每晚 运行 mysql 备份,这很好,因为这一切都是公平的静态数据。