我在工业环境(隔离网络)中拥有几台服务器,用于收集一些相对简单的遥测数据。我们在大约 30 天内生成了大约 10GB 的遥测历史记录。
所有遥测数据都进入一组表,这些表分为两种类型:当前状态和历史。状态表通常有 16 行或更少。历史表可能相当大,但总数约为 11GB。遥测数据以每秒不到 100 个样本的速度传入,并且历史表仅在发生变化或 30 秒过去时才会更新。从我的粗略检查来看,历史更新大约有 10 次中有 9 次被跳过。因此大多数情况下,每个样本都会导致一次 REPLACE INTO 到大约六个表中的一个中。
所有这些都是在 Supermicro 1U 服务器上的 Ubuntu 服务器 14.04(64 位)上运行的,这些服务器装有 2015 年左右的 Xeon 处理器。我不在工厂,所以无法检查确切的型号。
每台服务器都有 32GB 的 ECC RAM。
磁盘采用 RAID 1 配置,有 4 个驱动器(工厂的技术人员在驱动器出现故障时不会迅速采取行动,因此我们需要大量备份)。所有磁盘都使用 smartctl 持续监控,当其中一个显示故障或警告时,我们会更换它。12 月,我们更换了其中一台服务器的磁盘,并对另一台服务器做了同样的事情。
在这两台服务器上,MySQL 的性能通常都很好,状态表更新的响应时间为个位数毫秒。然而,我们得到了极端的异常值。有时,每天多次,通常每小时多次,我们会看到单个 REPLACE INTO 到 16 行状态表需要 1.5 秒以上。这触发了我们丢失遥测数据的警报,所以这非常烦人。
所有表都是 InnoDB,每个表一个文件。文件系统 (ext4) 启用了 Discard。我尝试更改 MySQL 参数以禁用提交时同步(而是使用定期同步),但似乎没有效果。我为 InnoDB 设置了一个 1GB 日志,数据库文件本身比 RAM 小得多。
RAM 大部分(约 60%)是缓存数据。
我尝试将状态表的表类型更改为 MyISAM,但问题仍然存在,没有任何变化。
我更改了数据记录器,这样每个表都由一个线程处理,并将批量排队更新线程化为提交。除非发生一次巨大的延迟,否则提交中很少会出现多个更改。
MyISAM 没有改变任何东西(我的意思是行为上根本没有明显的变化),这一事实让我怀疑是 RAID。
这些磁盘是全新的(不到两周)Crucial MX500 驱动器,1TB。是的,这些是消费级驱动器,但写入率相当低。而且,我们始终将文件系统的占用率保持在 40% 以下。
我不知道下一步该怎么做。这是 RAID 问题吗?这是 MySQL 配置问题吗?
我发现所有状态表都存在延迟,即使是只有 1 行的状态表也是如此。在某些情况下,行有点宽(其中一个有 125 列),但它们仍然非常非常小。
状态/状况表确实有主键来确保数据的唯一性。
有人能告诉我下一步该去哪里找吗?再说一次,这是一个隔离网络上的工业环境,因此一次下载大量工具非常麻烦,而且所有进出的软件都受到严格控制。
在服务器首次安装时,我没有足够聪明地安装 iostat。但是,使用 hdparm -tT 进行的原始测试似乎表明底层磁盘上一切正常。smartctl 中没有磁盘显示问题。
磁盘更换是一次完成的,因此 RAID 实际上是旧 RAID(基于 MX200)。更换磁盘时不会从头开始重建 RAID。
有参考资料提到了此版本的 MySQL(5.5 左右)和 REPLACE INTO 的一个已知问题,但我读到的任何内容都没有表明我应该看到性能有如此大的变化。
任何想法,将不胜感激!
答案1
写入期间的停滞(您似乎最常这样做)可能表示innodb_log_file_size
已满并正在等待刷新。5.5 中这些的默认大小非常小。将大小增加到 512M 并将实例增加到 4 将是一个不错的开始。请遵循以下参考。在数据加载期间观察这些的时间戳差异(数据目录的顶层)。如果它们都大致在同一分钟,则这些还不够大。还要查看SHOW ENGINES INNODB STATUS
输出。
參考文獻:手动更改重做日志大小不过,我会将旧文件移开,而不是删除它们,这样您就可以在需要时将它们移回。备份可以节省工作量。
还应将其innodb_buffer_pool_size
设置为一个大小来容纳活动工作集(70%的可用内存是一个好的开始,然后查看SHOW GLOBAL STATUS
使用了多少)。
确保启用了慢查询日志并设置适当的阈值将有助于检测其他慢查询。
參考文獻:慢查询日志手册