新建连接失败?

Posted xiepaup

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了新建连接失败?相关的知识,希望对你有一定的参考价值。

 关于链接数据库报错: ERROR 1135 (HY000): Can‘t create a new thread (errno 11); if you are not out of available memory, you can consult the manual for a possible OS-dependent bug

看到这个信息会有些迷惑,大概就是要么是内存不够了,要么是遇到 OS 的bug了。但是通过free命令查看我们的内存是足够的,难道真的就是OS 的bug ?不会这么巧吧。

既然说的是内存不够了, 猜测有可能是某个资源确实是越到了瓶颈,那么执行ulimit看看呢:

[[email protected] ~]$ ulimit -a
core file size (blocks, -c) unlimited
data seg size (kbytes, -d) unlimited
scheduling priority (-e) 0
file size (blocks, -f) unlimited
pending signals (-i) 127405
max locked memory (kbytes, -l) 64
max memory size (kbytes, -m) unlimited
open files (-n) 204800
pipe size (512 bytes, -p) 8
POSIX message queues (bytes, -q) 819200
real-time priority (-r) 0
stack size (kbytes, -s) 10240
cpu time (seconds, -t) unlimited
max user processes (-u) 1024 ----> 这里似乎有点猫腻
virtual memory (kbytes, -v) unlimited
file locks (-x) unlimited

到这里可以发现max user processes 这个地方似乎有点小,而我们的DB的连接数恰好达到1024,看起来和这里的限制有很大的关系,而这个限制一般情况下我们是通过 /etc/security/limits.conf这个文件配置的:

[[email protected] ~]$ cat /etc/security/limits.conf |grep -vE ‘^#|^$‘
soft nofile 204800
hard nofile 204800

通过cat 这个文件后发现并没有限制这么小呢,猜想会不会是limit.d目录下还有另外的配置,从而发现这个目录下还有个隐藏的配置文件90-nproc.conf,打开该文件一看果不其然是有个限制。

[mysql@xxxx ~]$ cat /etc/security/limits.d/90-nproc.conf 
# Default limit for number of user‘s processes to prevent
# accidental fork bombs.
# See rhbz #432903 for reasoning.
* soft nproc 1024

通过修改这个值,然后重启DB后,我们就可以创建更多的连接了。

到此问题已经解决了,那么留下几个问题:

  1. 为什么会是90-nproc.conf 这个文件呢?
  2. 对于一个已经启动的进程如果查看这个进程的资源限制呢?
  3. 如果动态的修改这些限制而不重启进程?

    • 关于为什么会是 90-nproc.conf 这个文件的值会生效? 可以查看Linux 源代码 pam_limits.c,定位 pam_sm_open_session 这个函数。它会先读取limits.conf 文件,然后在看limits.d 目录下是否存在 *.conf 的配置文件,如果有这样的配置文件,那么依次读取进来,覆盖 limits.conf 的相关配置。
retval = parse_config_file(pamh, pwd->pw_name, pwd->pw_uid, pwd->pw_gid, ctrl, pl);
if (retval != PAM_SUCCESS || pl->conf_file != NULL)
/* skip reading limits.d if config file explicitely specified */
goto out;

/* Read subsequent *.conf files, if they exist. */
if (!glob_rc) {
/* Parse the *.conf files. */
for (i = 0; globbuf.gl_pathv[i] != NULL; i++) {
pl->conf_file = globbuf.gl_pathv[i];
retval = parse_config_file(pamh, pwd->pw_name, pwd->pw_uid, pwd->pw_gid, ctrl, pl);
if (retval != PAM_SUCCESS)
goto out;
}
}
  • 如何得知我们的进程启动时候的资源限制如何? 
    可以通过 ps找到这个进程的PID ,然后 cat /proc/$PID/limits 文件得到进程资源限制
[[email protected]_naruto_192-168-3-59 ~]# cat /proc/25675/limits 
Limit Soft Limit Hard Limit Units
Max cpu time unlimited unlimited seconds
Max file size unlimited unlimited bytes
Max data size unlimited unlimited bytes
Max stack size 10485760 unlimited bytes
Max core file size unlimited unlimited bytes
Max resident set unlimited unlimited bytes
Max processes 102400 102400 processes
Max open files 204800 204800 files
Max locked memory 65536 65536 bytes
Max address space unlimited unlimited bytes
Max file locks unlimited unlimited locks
Max pending signals 127405 127405 signals
Max msgqueue size 819200 819200 bytes
Max nice priority 0 0
Max realtime priority 0 0
Max realtime timeout unlimited unlimited us
  • 有时候重启进程是个危险的操作,而且不是所以进程都可以随时重启的,那当我们知道这个进程存在资源限制的瓶颈时,怎么通过动态调整这个限制来确保我们的服务正常运行呢? 
    比如通过 /proc/$pid/limits 文件,得知我们的mysql进程存在OS级别的最大连接数限制,像调整一下这个限制可以通过一下步骤来完成:
[[email protected] ~]# ps -ef|grep mysqld
mysql 24831 1 0 Aug07 ? 00:00:00 /bin/sh /usr/local/mysql/bin/mysqld_safe --defaults-file=/etc/my.cnf --user=mysql
mysql 25675 24831 0 Aug07 ? 00:00:34 /usr/local/mysql/bin/mysqld --defaults-file=/etc/my.cnf --basedir=/usr/local/mysql --datadir=/data/mysqldata/data --plugin-dir=/usr/local/mysql/lib/plugin --log-error=/data/mysqldata/data/xxxxxx.err --pid-file=/data/mysqldata/data/xxxxx.pid --socket=/data/mysqldata/mysql.sock --port=xxxx
[[email protected] ~]# echo -n "Max processes=204800:204800" > /proc/25675/limits
[[email protected] ~]# cat /proc/25675/limits
Limit Soft Limit Hard Limit Units
Max cpu time unlimited unlimited seconds
Max file size unlimited unlimited bytes
Max data size unlimited unlimited bytes
Max stack size 10485760 unlimited bytes
Max core file size unlimited unlimited bytes
Max resident set unlimited unlimited bytes
Max processes 204800 204800 processes
Max open files 204800 204800 files
Max locked memory 65536 65536 bytes
Max address space unlimited unlimited bytes
Max file locks unlimited unlimited locks
Max pending signals 127405 127405 signals
Max msgqueue size 819200 819200 bytes
Max nice priority 0 0
Max realtime priority 0 0
Max realtime timeout unlimited unlimited us

修改了这个值后是否真的有效?如何验证?我们可以通过把这个值该小后,然后不断的增加连接数,当连接数达到我们的限制时,看看是否会报错;然后在动态修改这个值,看看连接能否建立。 
mysql 连接可以简单的写个for循环,然后每个连接sleep 2秒钟 for i inseq 150;do mysql -uxxx -pxxxx -Pxxx -h xxxx -e "select sleep(3)" & done

注: 动态的修改了/proc/$pid/limits 值之后,只是临时生效,如果进程重启这个限制又会重新读取配置文件的值,一劳永逸的办法是修改完成进程运行时的限制,然后在修改配置文件的参数。

以上是关于新建连接失败?的主要内容,如果未能解决你的问题,请参考以下文章

导致资产预编译在heroku部署上失败的代码片段

Navicat怎么连接Sqlite数据库

Sublime Text3自定义代码片段

新建sql注册提示无法打开用户默认数据库 登录失败,怎么解决

从流中读取失败 - MySqlException

Python之如何优雅的重试