關於鏈接資料庫報錯: 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 ...
關於鏈接資料庫報錯: 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看看呢:
[mysql@xxxx ~]$ 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
這個文件配置的:
[mysql@xxxx ~]$ 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後,我們就可以創建更多的連接了。
到此問題已經解決了,那麼留下幾個問題:
- 為什麼會是
90-nproc.conf
這個文件呢? - 對於一個已經啟動的進程如果查看這個進程的資源限制呢?
-
如果動態的修改這些限制而不重啟進程?
- 關於為什麼會是
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
文件得到進程資源限制
[root@Rus_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級別的最大連接數限制,像調整一下這個限制可以通過一下步驟來完成:
[root@xxxx ~]# 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
[root@xxxx ~]# echo -n "Max processes=204800:204800" > /proc/25675/limits
[root@xxxx ~]# 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 in
seq 150;do mysql -uxxx -pxxxx -Pxxx -h xxxx -e "select sleep(3)" & done
註: 動態的修改了/proc/$pid/limits 值之後,只是臨時生效,如果進程重啟這個限制又會重新讀取配置文件的值,一勞永逸的辦法是修改完成進程運行時的限制,然後在修改配置文件的參數。