最近新上了一批服務器,內核升級到了2.6.32版本,部署完MySQL實例后上到線上,直接負載沖到15,cpu使用達到700%。
01:20:01 PM runq-sz plist-sz ldavg-1 ldavg-5 ldavg-15 03:50:01 PM 34 1506 22.95 18.11 11.78 01:20:01 PM CPU %user %nice %system %iowait %steal %idle 03:50:01 PM all 95.13 0.00 3.31 0.06 0.00 1.49
當時就有點蒙,io並不是瓶頸,業務也米有變更,線上的服務器都運行正常,為什么這台新機器就變成這個模樣了呢?
最后才發現又是一個ulimit的坑啊,之前對於ulimit -n已經碰了多次頭,這次又差點碰的頭破血流,萬幸灰度上了1台slave,並沒有影響到線上。
這次碰到的問題是ulimit -u,這個-u是做什么用的呢?
core file size (blocks, -c) 0 data seg size (kbytes, -d) unlimited scheduling priority (-e) 0 file size (blocks, -f) unlimited pending signals (-i) 514875 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) 204800 virtual memory (kbytes, -v) unlimited file locks (-x) unlimited
可以從上面看出,用來限制max user processes的數量的。
但是這個user processes是什么呢?
Linux itself has a Max Processes per user limit. This feature allows us to control the number of processes an existing user on the server may be authorized to have
這個ulimit -u是用來限制每個用戶的最大processes數量。如果ulimit -u進行了限制那么每個linux用戶可以派生出來的process就會被限制再這個數值之內。
那么這個限制和MySQL有什么關系呢,我們看如下的測試:
首先,在一台服務器上起動兩個MySQL實例,分別限制max connetcionts=1024 , ulimit -u=1024
然后,在一台服務器上運行類似下面的腳本
for i in `seq 1 2010` do echo $i mysqlha_login.sh -h 10.77.7.56 -P 3306 -e'system sleep 60;' & mysqlha_login.sh -h 10.77.7.56 -P 3307 -e'system sleep 60;' & done
當i的數值超過1009的時候就會出現如下報錯
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
這就是無法再創建出新的process了。
如果我們將ulimit -u改為10240,再進行一次測試呢?
User myadmin already has more than 'max_user_connections' active connections
報錯就變更為我們常見的超過最大連接數的報錯了。
so,對於提供長鏈接的MySQL服務,建議都講這個值調整為10240或者更大。對於提供短鏈接的服務,暫時並沒有出現本次發現的錯誤。
那么最后,如何修改這個數值呢?
首先,內核不同這個參數的默認設置是不同的,請大家小心。
2.6.18 ore file size (blocks, -c) 0 data seg size (kbytes, -d) unlimited scheduling priority (-e) 0 file size (blocks, -f) unlimited pending signals (-i) 139264 max locked memory (kbytes, -l) 32 max memory size (kbytes, -m) unlimited open files (-n) 288000 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) unlimited virtual memory (kbytes, -v) unlimited file locks (-x) unlimited 2.6.32 core file size (blocks, -c) 0 data seg size (kbytes, -d) unlimited scheduling priority (-e) 0 file size (blocks, -f) unlimited pending signals (-i) 514875 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
然后,一般來說,修改ulimit的數值,只需要修改/etc/security/limits.conf即可,但是這個參數需要修改/etc/security/limits.d/90-nproc.conf。
至於為什么需要修改這里,請看褚霸的這篇blog:http://blog.yufeng.info/archives/2568
但是,還有一個問題,這個參數需要在mysqld啟動之前調整,如果mysqld已經啟動,再動態調整是無效的。(大家都知道stop start mysql是一件比較麻煩的事情,涉及線上業務就更麻煩了)
那么,有沒有可以動態調整的方法呢?
echo -n 'Max processes=SOFT_LIMITS:HARD_LIMITS' > /proc/`pidof mysqld`/limits
通過如上命令就可以動態調整已經存在的mysqld的processes限制了。
參考閱讀:
http://tldp.org/LDP/solrhe/Securing-Optimizing-Linux-RH-Edition-v1.3/x4733.html
http://www.mysqlperformanceblog.com/2013/02/04/cant_create_thread_errno_11/