我今天突然遇到了 MySQL 问题。
细节:
- 操作系统:CentOS 版本 5.7
- 服务器类型:在 mediatemple DV 4.0 包上运行的 Parallels virtuozzo 容器
- 平均总内存使用量:<500mb
- 允许的总内存使用量:1gb(共享池的一部分仅用于紧急情况,仅保证用户使用 500mb)
- 处理器:>1ghz
- 使用率最高的主数据库大小:275mb 和 107mb
- 服务器堆栈:nginx 1.0.10、mysql 5.1.54、带有 php-fpm 的 php 5.3.8
- innodb_buffer_pool_size=100M
- php-fpm 最大子节点数:5
- Webapps:基于 php 的自定义网站、magento 和 drupal
- 慢查询超时设置为 1 秒
我完成的诊断步骤:
- 尚无法重新启动容器 - 今晚国内流量下降后我会再尝试。
- 启用mysql和php-fpm slowlog。
- 发现 php-fpm slowlog 中执行数据库查询的函数有时需要超过 1 秒才能完成
- 发现 mysql slowlog 中的一些简单查询需要超过 1 秒才能完成,而这些查询应该只需不到 1 秒的时间。
- 最有趣的是 - 执行时间似乎有时会激增。查询几次需要 0.2 秒,然后有一次运行同一查询需要 8 秒。这些结果是通过 mysql 命令行运行原始 SQL 查询来验证的。
- 顶部没有透露任何太有趣的东西
- 我唯一看到的与资源相关的问题是平均负载远高于正常水平
- 到今天为止,mysql 一直很好,自昨天以来数据库没有发生重大变化。
- 有时情况非常糟糕,我在执行 60 秒后看到了网关错误。
- Innodb 的平均读取速度为每秒 300-1400 次。
- Mysql 每秒执行 3-10 个查询
- 2 小时正常运行时间内的慢速查询数为 171(慢速超时为 1 秒)
- 尝试多次重启 mysql、nginx、php-fpm
例如:
UPDATE `catalogsearch_query` SET `query_text` = 'EW 90', `num_results` = '7532', `popularity` = '99180', `redirect` = NULL, `synonym_for` = NULL, `store_id` = '1', `display_in_terms` = '1', `is_active` = '1', `is_processed` = '1', `updated_at` = '2012-05-08 21:38:31' WHERE (query_id='31');
此查询一次耗时 17 秒,其余时间大约耗时 0.079 秒。但时间会有所不同,有时为 1 秒,有时为 0.004 秒。这是在反复运行相同的查询,每次间隔几秒钟。
大多数表都是 innodb,有时我注意到锁定时间占查询执行时间的 90%,但大多数时候锁定时间并不重要。
知道这里发生什么事了吗?
答案1
听起来几乎肯定是一个影响正在发生的事情的边缘问题,并且在像 VPS 这样的受限和竞争环境中运行 Magento 时相当典型。
如果您的配置以前运行良好,并且您没有更改任何代码或安装任何扩展 - 那么它将是一个外部影响,很可能是流量的增加 - 但对于 VPS 来说,它更有可能增加 I/O 活动。
这听起来就像 I/O 等待 - 只需安装像 Munin 这样的图形工具就可以最终证明这一点(显示 MySQL 慢查询与 I/O 活动/等待之间的相关性)。
我将参考其他几篇同样的帖子 - 因为在 VPS 中运行 Magento 总是会产生类似的行为。
答案2
最可能出现的两个问题是:
1)你的查询被另一个查询阻止 - 检查你的慢查询日志,了解启动更新时正在运行什么
2) 您的虚拟机没有被主机调度。设置一个看门狗脚本,将心跳写入日志文件
可能还有其他原因,但除非你能排除上述两个原因,否则讨论它们就没有多大意义。
就解决问题而言,前者只是查询调整的问题,而对于后者,您需要与管理主机的人员交谈。
答案3
是什么意思:
SHOW CREATE TABLE catalogsearch_query\G
SHOW INNODB STATUS;
SELECT * FROM information_schema.PROCESSLIST WHERE State='Locked' ORDER BY Time;
看起来像 ?
我怀疑您遇到了“打开表/关闭表”问题。我不会过多地重启您的数据库,它需要时间来预热,尤其是在进行大量更新时。
为了使其完整,我也希望看到这一点:
SHOW STATUS LIKE '%cache%';
SHOW STATUS LIKE '%table%';
而这一切都是在遇到麻烦时发生的,我敢打赌,当你遇到麻烦并进行“刷新桌子”时,这将花费很长时间。
一些可以加快处理速度的重要配置参数:
innodb_log_buffer_size = 16M
innodb_file_per_table = 1
innodb_open_files = 16000
innodb_io_capacity = 400
innodb_flush_log_at_trx_commit = 2
innodb_flush_method = O_DIRECT
innodb_thread_concurrency=8
innodb_lock_wait_timeout = 90
请注意,这是来自 MariaDB,因此是强化版的 mysql。(XtraDB)特别是,per_table 设置非常激进,但只会影响新表,如果您希望问题表位于自己的 innodb 中,则需要重新创建它们。这与 O_DIRECT 刷新方法和 trx_commit=2(首先阅读此内容!)一起将大大加快速度,尤其是在进行大量更新/插入时。
希望这可以帮助。