我在我的 linode 服务器上运行一个应用程序 PHPlist,同时运行 12 个 PHP 脚本,每个脚本都打开一个 MySQL 连接。现在,当我访问 PHPlist 时,它经常显示此错误:
Fatal Error: Sorry, the server is currently too busy, please try again later.
当我尝试访问 phpMyAdmin 时,它显示 #1040 错误。通过cron作业运行的 PHP 脚本的输出显示:
cron
PHP Warning: mysqli_connect(): (HY000/1040): Too many connections
我正在使用带有 phpMyAdmin 的服务器上的 LAMP 堆栈;top终端中的输出显示mysqld使用 100-130% CPU。当我试图解决这个问题时,我得到了一些线索:
top
mysqld
有很多变量要设置,但我无法确定具体的变量,我从中获得了一些参考: 连接太多 和http://dev.mysql.com/doc/refman/5.5/en/table-cache。 html
但是根据我的使用情况如何增加内存以及对我来说最大内存困难是多少。
在我的服务器上,我使用了大约 12 个 PHP 脚本、用于发送电子邮件的 PHPlist 应用程序以及用于用户注册的主要数据库。
请帮我解决这个问题。
首先你需要做的是运行这个查询:
SELECT user,host FROM mysql.user WHERE super_priv='Y' AND CONCAT(user,'@',host) <> 'root@localhost';
这将列出所有拥有SUPER 权限的用户。大多数进行与应用程序相关的 DB 处理的用户不需要此权限。根据MySQL 文档,具有 SUPER 权限的用户可以执行以下操作:
mysqladmin kill
您需要以 root@localhost 身份登录并撤销 SUPER 权限,如下所示:
UPDATE mysql.user SET super_priv='N' WHERE super_priv='Y' AND CONCAT(user,'@',host) <> 'root@localhost'; FLUSH PRIVILEGES;
一旦你这样做了,每当所有用户淹没 mysql 连接时,就只能root@localhost登录。毕竟,如果每个人和他的祖母都拥有超级特权,这将root@localhost永远无法与其他人联系。如果 max_connections 为 200 并且您需要将其提高到 300 而无需重新启动 mysqld,则可以使用以下命令动态增加max_connections :
root@localhost
mysql> SET GLOBAL max_connections = 300;
这将允许更多的连接立即生效,但不要一时兴起就随意增加数量。您必须确保 mysql 有足够的 RAM 来容纳增加的内存。
CAVEAT : 如果您将 max_connections 动态更改为 300,请将其放入 /etc/my.cnf
[mysqld] max_connections=300
您可以在 MySQL 数据库服务器上运行 mysqltuner.pl。如果没有,请运行以下命令:
cd wget mysqltuner.pl perl mysqltuner.pl
Performance Metrics 下的第 3 行有这个
-------- Performance Metrics ------------------------------------------------- [--] Up for: 8d 20h 46m 22s (8M q [10.711 qps], 129K conn, TX: 90B, RX: 19B) [--] Reads / Writes: 4% / 96% [--] Total buffers: 2.1G global + 5.4M per thread (2000 max threads) [OK] Maximum possible memory usage: 12.6G (80% of installed RAM)
看到每个线程 5.4M 了吗?这与 max_connections 相乘。在此示例中,最大 RAM 约为 10.8G。因此,每次增加 max_connections 时,都应该运行 mysqltuner.pl 并检查是否按操作系统占用太多内存。
在任何情况下,限制拥有 SUPER 权限的用户都可以让这些用户有机会减轻数据库连接对 mysqld 的泛滥。