Error establishing a database connection #1040 - Too many connections

昨天晚上遭遇

Error establishing a database connection 数据库错误提示: error #1040 - Too many connections

翻译成中文是:一个错误的数据库链接.

大致情况如下,昨晚上康福(camfrog)发现好多人都无法都提出视频总是知道关闭,于是便写了一篇临时解决方法.http://www.lfeng.org/2011/154.html

发在聊天室里面,我估计着访问量应该有点吧!接着流量增加,再接着便出现.

Error establishing a database connection

于是便上主机控制面板查看,链接数据库时.提示错误:#1040 - Too many connections (太多的连接)

而我主机是不限制链接的,查找谷歌一番结果如下:

是数据库表错误,我把整个数据库表修复和优化了一次

把define(’DB_HOST’, ‘localhost’)里面的localhost改成你数据库的地址,比如我的本地数据库地址是:localhost:6033/wordpress,

就把localhost改成localhost:6033/wordpress

出现这种情况的原因可能是:

1、无法连接到Wordpress使用的数据库。

你的wp-config.php中的数据库用户名和密码错误,或者你的数据库所在服务器挂掉了!也有可能是服务商短时间内限制(访问量突然暴涨的博客或使用一些消耗数据库连接的WP插件)。

解决办法是,确认wp-config.php中的用户名和密码信息正确。确认WP使用的数据库服务器没有挂掉(可以ping或直接重启?!)。确认数据库连接方式,是远程连接还是本地连接,有些配置的远程连接的可能出现连不上数据库的情况,也就会出现这个“Error establishing a database connection”提示,一般虚拟空间(GD的空间使用的远程数据库连接)或合租空间都是使用的本地连接(localhost)。

2、若服务器数据库是刚刚升级到 mysql 5.0 以上,之前WP博客正常可访问。

这可能是由于mysql 5.0采用了一种新的密码验证机制,这需要客户端的版本要在4.0以上(PHP中的MYSQL客户端可以查看phpinfo得到),连接数据库时是用旧的密码机制,这会出现“Client does not support authentication protocol requested by server” 这样的错误提示,wordpress中就提示“Error establishing a database connection (可能密码错误)”。

解决办法:

方法1、在mysql中为wordpress数据库新建一个控制账户,然后修改wp-config.php中的数据库用户名和密码配置信息即可。方便简单!!

方法2、在mysql下:

mysql> SET PASSWORD FOR
-> ‘clin003′@’clin003.com’ = OLD_PASSWORD(‘newpwd’);
mysql> FLUSH PRIVILEGES;
这里的clin003替换成使用wordpress数据库的用户名,clin003.com替换成localhost或者某个域名,newpwd是该用户对应的密码。

还有一点是,查看phpinfo(),找MYSQL_SOCKET显示的mysql.sock的路径,确认mysql.sock的确在此路径下,否则需要做一个符号链接。比如phpinfo里显示MYSQL_SOCKET路径为/var/lib/mysql/mysql.sock,但实际上位于 /tmp/mysql.sock,可在命令行输入:

ln -s /tmp/mysql.sock /var/lib/mysql/mysql.sock

3、mysql服务设置不当,导致mysql连接数量超过限定值,或者应用程序设计有问题,导致大量休眠连接不能及时释放。

解决办法:
登陆mysql服务器

mysql -u root -p

使用命令

show processlist;

查看当前连接数量。
如果进程过多,或存在大量超时的休眠sleep连接,编辑/etc/mysql/my.cnf

vim /etc/mysql/my.cnf

在[mysqld]字段处,添加,或去掉注释

max_connections = 500 #增加mysql连接数
wait_timeout = 10 #断开超过10秒的连接

4、是wp_options数据库表错误,我把整个数据库表修复和优化了一次

wp_options中的表前缀wp根据自己实际情况查看!

WordPress出现错误时,可以通过 debug 参数调试:

根据Wp-config.php的调试功能排错

1、在 wp-config.php 有个 debug 的参数,打开这个参数,修改为:

define(‘WP_DEBUG’, ‘true’);

2、根据报错提示解决问题,比如以下错误:

WordPress database error: [Table './clin003_com/wp_options' is marked as crashed and should be repaired]
SELECT autoload FROM wp_options WHERE option_name = ‘_transient_doing_cron’

WordPress database error: [Table './clin003_com/wp_options' is marked as crashed and should be repaired]
SELECT autoload FROM wp_options WHERE option_name = ‘_transient_timeout_doing_cron’

WordPress database error: [Table './clin003_com/wp_options' is marked as crashed and should be repaired]
SELECT option_value FROM wp_options WHERE option_name = ‘_transient_doing_cron’ LIMIT 1

wp_options 表坏了,需要被修复,使用 mysql 客户端。
进 mysql 使用修复的命令修复:

mysql>repair table wp_options;
也可以通过phpMyAdmin来进行修复。

3、问题解决,关掉 DEBUG。

根据mysql的日志记录排错

在mysql的log日志文件

mysql/data/

里面找到一个.err结尾的文件,打开。看见了一排

‘.\clin003_com\wp_options’ is marked as crashed and should be repaired
‘.\clin003_com\wp_options’ is marked as crashed and should be repaired
‘.\clin003_com\wp_options’ is marked as crashed and should be repaired

 

#1040 - Too many connections

解决办法就是把MYsql的数据库链接数修改一下:

服务器经常出现1040 Too many connections的错误

1、修改配置文件文件

修改/etc/my.cnf这个文件,在[mysqld]中新增max_connections=N,如果你没有这个文件请从编译源码中的support-files文件夹中复制你所需要的*.cnf文件为到/etc/my.cnf。我使用的是my-medium.cnf,中型服务器配置。例如我的[mysqld]的内容如下

[mysqld]

port              = 3306

socket            = /tmp/mysql.sock

skip-locking

key_buffer = 160M

max_allowed_packet = 1M

table_cache = 64

sort_buffer_size = 512K

net_buffer_length = 8K

read_buffer_size = 256K

read_rnd_buffer_size = 512K

myisam_sort_buffer_size = 8M

max_connections=1000

由于对mysql还不是很熟悉,所以很多参数没有修改。哈哈。。

2、非使用mysqld脚本自动启动的用户。

修改$MYSQL_HOME/bin/mysqld_safe文件

例如:/usr/local/mysql/bin/mysqld_safe这个文件

grep -n 'max_connection' $MYSQL_HOME/bin/mysqld_safe

修改对应行号的max_connections参数值

以上方法为老翁自己参考网上的做法写的。我个人使用第1 种,如果有什么错误欢迎大家讨论。

 

方法二:

以前有朋友问过我,为什么他的网站出现Too many connections 错误。因为我自己没有遇到过这个问题,那时候工作也忙,没有时间去考虑这

个问题。几个星期前,到现在的公司工作,有朋友告诉我,我现在的公司的网站上出现同样的问题,到了非要搞清楚的地步了,于是在PHP手册

里面找关于mysql_connect和mysql_pconnect的资料,下面是在php手册中对这两个函数的描述:

-------- mysql_connect -----------

函数原型:

resource mysql_connect ( [string server [, string username [, string password [, bool new_link [, int client_flags]]]]])

返回:

如果成功则返回一个 MySQL 连接标识,失败则返回 FALSE。

描述:

mysql_connect() 建立一个到 MySQL 服务器的连接。当没有提供可选参数时使用以下默认值:server = 'localhost:3306',username =

服务器进程所有者的用户名,password = 空密码。

如果用同样的参数第二次调用 mysql_connect(),将不会建立新连接,而将返回已经打开的连接标识。参数 new_link 改变此行为并使

mysql_connect() 总是打开新的连接,甚至当 mysql_connect() 曾在前面被用同样的参数调用过。参数 client_flags 可以是以下常量的组合

:MYSQL_CLIENT_COMPRESS,MYSQL_CLIENT_IGNORE_SPACE 或者 MYSQL_CLIENT_INTERACTIVE。

注: new_link 参数自 PHP 4.2.0 起可用。

client_flags 参数自 PHP 4.3.0 起可用。

一旦脚本结束,到服务器的连接就会被关闭。除非之前已经调用了 mysql_close() 来关闭它。

------- mysql_pconnect -------------

函数原型:

resource mysql_pconnect ( [string server [, string username [, string password [, int client_flags]]]])

返回:

如果成功则返回一个正的 MySQL 持久连接标识符,出错则返回 FALSE。

描述:

mysql_pconnect() 建立一个到 MySQL 服务器的连接。如果没有提供可选参数,则使用如下默认值:server = 'localhost:3306',

username = 服务器进程所有者的用户名,password = 空密码。client_flags 参数可以是以下常量的组合:MYSQL_CLIENT_COMPRESS,

MYSQL_CLIENT_IGNORE_SPACE 或者 MYSQL_CLIENT_INTERACTIVE。

server 参数也可以包括端口号,例如 "hostname:port",或者是本机套接字的的路径,例如 ":/path/to/socket"。

注: 对 ":port" 的支持是 3.0B4 版添加的。

对 ":/path/to/socket" 的支持是 3.0.10 版添加的。

-------- 两者之间的区别 --------------

mysql_pconnect() 和 mysql_connect() 非常相似,但有两个主要区别。

首先,当连接的时候本函数将先尝试寻找一个在同一个主机上用同样的用户名和密码已经打开的(持久)连接,如果找到,则返回此连接

标识而不打开新连接。

其次,当脚本执行完毕后到 SQL 服务器的连接不会被关闭,此连接将保持打开以备以后使用(mysql_close() 不会关闭由

mysql_pconnect() 建立的连接)。

可选参数 client_flags 自 PHP 4.3.0 版起可用。

此种连接称为"持久的"。

看到这里,写一条代码来测试一下

/*

* pconnect_test.php

*/

$link = mysql_pconnect("localhost", "mysql_user", "mysql_password")

or die("Could not connect: " . mysql_error());

print ("Connected successfully");

通过刷新网页的方式执行这条代码,发现每执行一次,mysql的进程数就增加一个。在这里我不禁有了疑问。上面说mysql_pconnect这个函

数的使用的时候,不是说"当连接的时候本函数将先尝试寻找一个在同一个主机上用同样的用户名和密码已经打开的(持久)连接,如果找到

,则返回此标识而不打开新连接"么?为什么我每刷新一次页面他就给我打开一个新的连接呢?

考虑到这有可能是PHP的bug,我到PHP的bug列表中找关于和too many connections 有关的条目。

相关的话题主要有三个,分别是

#11966         mysql_pconnect opens new connections with the same parameters

#26117         Persistent connection not reused

#13589         Persistent connections stay open and accumulate

描述比较长,我就不在这里贴,具体的内容你自己去看。重点主要是"当一个进程打开一个mysql的持续连接,只要该进程还存在,这个持续

的连接就不会断开,而且每一个进程会打开一个mysql的持续连接,而不能使用其他进程打开的持续连接"。

到这里,我把相关的信息发给上海的朋友张宏,他提示我把apache的子进程数限制到不高于mysql的最大连接数。我问了我们的系统管理员

,他说我们的服务器上apache的最大子进程数是256,而mysql的最大连接数限制为600。就是说mysql的最大连接数已经远远超过httpd的进程数

,为什么还会出现Too many connections 这样的错误呢?答案就在于PHP程序。打开以前同事写的程序,发现同一个运行脚步中过多的调用

mysql_pconnect函数。如果在应用服务器上,每一个httpd子进程使用一个php脚本,每一个php脚本打开不止一个mysql的连接。因为httpd所产

生的子进程的生存期是apache服务器指定的,一般服务器不重启,这些进程就一直存在。就算服务器重启,也可以指定保存这些进程。由于进

程的存在,那么这些连接都不会断掉,并且每个进程打开几个连接数,那么统计起来,连接数就达到了mysql限制的最大连接数。这时就出现

Too many connections 错误。

小结一下,要保证你的系统不会出现Too many connections 错误,需要注意两点:

1.保证你的apache的最大进程数不超过mysql的最大连接数;

2.不要在程序里面用过多mysql_pconnect连接到同一个数据库服务器(一个就够了).这需要好的编码习惯和规范.特别是不断的给系统增加

新的功能,如果不注重系统架构和编码规范,当系统的复杂度到了一定的程度,整个系统就变得无法维护了.出现问题的时候解决起来就很麻烦了.

解决方法是修改/etc/mysql/my.cnf,添加以下一行:

set-variable = max_connections=500

或在启动命令中加上参数 max_connections=500

就是修改最大连接数,然后重启mysql.默认的连接数是100,太少了,所以容易出现如题错误.

本文著作权归作者 [  ] 享有,未经作者书面授权,禁止转载,封面图片来源于 [ 互联网 ] ,本文仅供个人学习、研究和欣赏使用。如有异议,请联系博主及时处理。

发表留言