文章為網路上截取,對於MySQL Open file分析的還不錯,故吸收後再分享給大家^^!!
由於最近在 mysql 上面安裝了一些系統,導致 DB 裡的 table 量大增,突然有一天 mysql 自己就掛點了,看了 log 後發現訊息如下:
引用:
/usr/sbin/mysqld: Can’t open file: ‘./xxxx/xxxx.frm’ (errno: 24)
………………………………………
[ERROR] /usr/sbin/mysqld: Can’t open file: ‘./xxxx/xxxx.frm’ (errno: 24)
[ERROR] Error in accept: Too many open files
[ERROR] Error in accept: Too many open files
網路上的討論有很多,包括調整系統本身的 fs.file-max 大小,還有在 /etc/my.cnf 中加入 open_files_limit 的設定值,但是實際上,光是這樣的調整是不夠或方向是不對的,因為 mysql 要開多少的 files,真正相關的不只這些設定。
相關的設定有:
/proc/sys/fs/file-max
這是系統資源配置的最高檔案數,設定值與記憶體大小有關,早期 ram 很貴的時代,這個值通常不會太大,所以 mysql 開的檔案數如果太多,確實可能被這個值限制住,但是現在動輒數 G 的 memory,這個值在我的 linux 系統上都內定開到 20 萬以上,因此問題不在這個值。 (若真想修改這個值,可以用 sysctl -w fs.file-max=##### 來修改,但系統重開後自動改回,可寫入 /etc/rc.local 開機執行)
ulimit -nulimit 可以查看每個 shell 的使用資源大小,-n 參數在 man page 中是寫 The maximum number of open file descriptors,換句話說,mysql 所處的 shell,真的能開的檔案只是 ulimit -n 的值,在我的系統上 ulimit -n 的值僅有 1024,所以就算 fs.file-max 有幾十萬,
mysql shell 可以開的就是 1024 而已,這才是關鍵所在。my.cnf 中的 table_cache, max_connections, open_files_limit 三個參數table_cache: mysql 5.1.3 版後已更名為 table_open_cache,指 mysql 開啟 table 的 cache file 數,一般 mysql 開一個 table 就會開啟 *.MYI 和 *.MYD 兩個檔,比方說我們用 phpMyAdmin 開一個有 100 個 tables 的 DB,mysql 會 cache 住 200 個 files。 (default: 64)
max_connections: 最高連線數。 (default: 100)
open_files_limit: mysqld 開啟的最高檔案數。 (default: 0)
理論上 mysqld 在 open file 後會 cache 住,那它要開到多少個檔案之後,才會去釋放掉 cache 的檔案?那就得看 my.cnf 裡面,table_cache, max_connections, open_files_limit 的值,如果 open_files_limits 的值為 0,就看 table_cache 和 max_connections 透過某個函數計算出來的值;如果 open_files_limits 的值不為 0,那應該是要看這個值的大小設定。
問題來了,那個函式怎麼算的,一般說法是 table_cache * 2 + max_connections,我在 my.cnf 原本的設定是 table_cache 1024, max_connections 500, open_files_limits 則不設 (default: 0),結果計算出來是 1024 x 2 + 500 = 2548,所以照理論來說 mysql 可以開到 2548 個檔案。但實際卻在我 DB table 數大增後,便很容易因為文章一開頭的 error 讓 mysql 掛點了。
仔細一看 log 後更可以進一步發現這個 [Warning] Could not increase number of max_open_files to more than 1024 (request: 2548)。
換句話說,如果 table_cache * 2 + max_connections 超過 1024 就會有警告,而 1024 便是 ulimit -n 那個 1024,即 shell 的限定使用資源。因此 mysql 真正會掛的主因是,它認為可以開到 2548 個檔,但系統只給它開到 1024 個檔,所以 mysql 就會一直去開第 1025 個檔而失敗,最後 mysql 就掛了…….
結論就是,不管我們要將我們的 mysql 設置 open_files_limit 或是使用 table_cache * 2 + max_connections,
都應該要注意 ulimit -n 的值才是正解,跟 fs.file-max 關連反而較小了。
PS: 要查看 mysql 開啟的 files 數,可先用
(1) #ps aux | grep mysql 看 mysql PID
(2) 再利用 #lsof -p PID# | wc -l 來統計。
至於要怎麼使用 ulimit 來修改 max open file呢?(1) 修改 /etc/bashrc ,在最下面加上一行
ulimit -HSn 32768
(2)另一種設定 max open file的方式:
修改 /home/adj/.bashrc,找個位置加入ulimit -HSn 32768
例如:要修改adj這個user 的 max open file,則修改 /home/adj/.bashrc 加入要設定的值即可。