通过mysql.sock在重负载下的PHP / MYSQL连接失败
Posted
技术标签:
【中文标题】通过mysql.sock在重负载下的PHP / MYSQL连接失败【英文标题】:PHP / MYSQL connection failures under heavy load through mysql.sock 【发布时间】:2015-05-03 21:18:47 【问题描述】:在问这个问题之前我已经阅读了很多内容,所以让我先说我没有用完连接、内存或 cpu,据我所知,我没有用完文件描述符。
无法通过socket '/var/lib/mysql/mysql.sock'连接本地MySQL服务器(11“资源暂时不可用”)
这在负载下随机发生 - 但我推得越多,php 越频繁地向我抛出这个。虽然发生这种情况,但我总是可以通过控制台本地连接,并通过 127.0.0.1 从 PHP 连接,而不是使用更快的 unix 套接字的“localhost”。
这里有一些系统变量可以排除常见的问题:
cat /proc/sys/fs/file-max = 4895952
lsof | wc -l = 215778 (during "outages")
可用连接的最高使用率:26% (261/1000)
InnoDB 缓冲池/数据大小:10.0G/3.7G(空间充足)
软文件999999 硬文件 999999我其实是在运行 MariaDB(服务器版本:10.0.17-MariaDB MariaDB Server)
这些结果是在正常负载下以及在非工作时间运行 mysqlslap 生成的,因此,慢查询不是问题 - 只是高连接数。
有什么建议吗?如有必要,我可以报告其他设置/数据 - mysqltuner.pl 说一切正常
再次说明,通过 IP 连接可以正常工作,并且在这些中断期间速度很快 - 我就是不知道为什么。
编辑:这是我的 my.ini(根据我最近的故障排除更改,某些值可能看起来有点高,请记住 MySQL 日志、系统日志或 dmesg 中没有错误)
socket=/var/lib/mysql/mysql.sock
skip-external-locking
skip-name-resolve
table_open_cache=8092
thread_cache_size=16
back_log=3000
max_connect_errors=10000
interactive_timeout=3600
wait_timeout=600
max_connections=1000
max_allowed_packet=16M
tmp_table_size=64M
max_heap_table_size=64M
sort_buffer_size=1M
read_buffer_size=1M
read_rnd_buffer_size=8M
join_buffer_size=1M
innodb_log_file_size=256M
innodb_log_buffer_size=8M
innodb_buffer_pool_size=10G
[mysql.server]
user=mysql
[mysqld_safe]
log-error=/var/log/mysqld.log
pid-file=/var/run/mysqld/mysqld.pid
open-files-limit=65535
【问题讨论】:
你的磁盘 I/O 是什么样的?如果您的瓶颈没有出现在内存、cpu 或连接上,则很可能与负载下的磁盘 I/O 跟不上 .sock 有关。你试过不使用套接字吗? 在我最糟糕的情况下,iowait 仍然为 0%(而且 html 页面的服务又好又快,控制台速度很快,等等,所以不是磁盘 IO 问题) - 我可以尝试不使用本地套接字 -但这只会通过在已经很忙的服务器的 TCP 堆栈上引入更多负载来滋生网络问题。我宁愿继续使用更快和推荐的本地套接字方法。 这是一个可能的错误。尝试更改您的版本 你如何运行你的 PHP 代码?例如 PHP-FPM 有一个文件描述符的最大限制设置,我不确定这是否只影响主进程或者它是否在所有工作进程之间共享,但您可能需要检查一下。 @AndréDaniel - 我制作了一个简单的测试脚本来尝试连接并输出任何错误,然后我从命令行运行它以从等式中删除 Web 服务。我还在凌晨 3 点使用 mysqlslap 生成负载以消除传入连接或复杂查询问题。底线是在中等负载下 PHP 和 Mysql 之间的套接字连接出现问题 - 但性能和 TCP 连接不受影响。 【参考方案1】:很可能是由于net.core.somaxconn
/proc/sys/net/core/somaxconn
的值是多少
net.core.somaxconn
# The maximum number of "backlogged sockets". Default is 128.
队列中尚未连接的连接。该队列之上的任何东西都将被拒绝。我怀疑你的情况。尝试根据您的负载增加它。
以root用户运行
echo 1024 > /proc/sys/net/core/somaxconn
【讨论】:
它设置为 4096,昨天我发现它作为本地套接字的 php-fpm/nginx 问题的解决方案发布时已更改。现在流量很低,我有机会再试一次,我发现错误已经消失了!我要奖励你这件事,因为我相信你是对的!这很可能是罪魁祸首,谢谢! 这是有关 net.core 更改的最终设置列表: net.core.somaxconn = 4096 net.core.netdev_max_backlog = 4096 net.core.rmem_max = 16777216 net.core.wmem_max = 16777216 很高兴知道您的问题已解决。谢谢【参考方案2】:这是可以而且应该通过分析来解决的。学习如何做到这一点是一项很棒的技能。
分析以找出在重负载下发生了什么...查询数量、执行时间应该是您的第一步。确定负载,然后进行正确的数据库配置设置。您可能会发现您需要优化 sql 查询!
然后确保 PHP 数据库驱动程序设置也对齐以充分利用数据库连接。
这里是 MariaDB 线程池文档的链接。我知道它说的是 5.5 版,但它仍然相关,并且该页面确实引用了 10 版。列出的设置可能不在您可以使用的 .cnf 文件中。
https://mariadb.com/kb/en/mariadb/threadpool-in-55/
【讨论】:
感谢您的坦率,但我已经这样做了很长一段时间,遵循最佳实践,阅读了许多有关该主题的书籍,并且以前从未遇到过此问题。我在这里发帖是因为无论查询(仅使用 mysqlslap 证明)在机器上放置适度( 我并不是要粗鲁,但我并不是在寻找“阅读手册”作为解决方案。我没有用完 CPU、RAM 或文件描述符,数据库并没有变慢,它的响应非常好。 dmesg 或 mysql 的日志中没有错误。这可能是操作系统或 php 问题,我不确定是哪一个,我来这里是为了获得一些帮助,因为经过广泛的研究,我很困惑 - 我已经阅读了手册。 这种方法是我用来解决此类问题的方法。我只是想让你查看设置而不是 RTFM。适合自己。 也许您也应该在 Stackexchange 的 ServerFault 站点中询问? (或替代) @Rob,对不起,我很沮丧。现在我已经仔细研究了我所知道的每一个手册和论坛,我不知道该去哪里找,我唯一的错误是含糊不清。我希望这里有人会遇到同样的问题并有解决方案。【参考方案3】:从我的脑海中,我可以认为 max_connections 可能是问题的根源。我会增加限制,至少消除这种可能性。
希望对你有帮助。
【讨论】:
感谢您的回答。我在上面提到我正在跟踪 - 可用连接的最高使用率:26% (261/1000)以上是关于通过mysql.sock在重负载下的PHP / MYSQL连接失败的主要内容,如果未能解决你的问题,请参考以下文章