來源:html
前些天說了一下如何修復損壞的MyISAM表,惋惜只會修復並不能脫離被動的境地,只有查明瞭故障緣由纔會一勞永逸。
若是數據庫服務非正常關閉(好比說進程被殺,服務器斷電等等),而且此時剛好正在更新MyISAM表,那麼發生損壞的機率就比較大。今天我要說的是另外一種狀況:頻繁的打開關閉MyISAM表文件形成MyISAM表損壞。
何時會出現頻繁的打開關閉MyISAM表文件的狀況呢?
先查看當前系統的table_cache設置,它的做用就是緩存表文件描述符,下降打開關閉表的頻率,若是這個參數設置得太小,那麼很快就會被佔滿,再有新請求過來的時候,就不得不關閉一些已打開的表以便爲新請求騰出空間,從而出現頻繁的打開關閉MyISAM表文件的狀況:
mysql> show variables like 'table%';
再查看當前系統的打開表的狀況:
mysql> show status like 'open%';
有兩項關鍵的結果:Open_tables和Opened_tables,他們的名字相似,其含義的區別在於:
Open_tables:表示當前打開的表數目。
Opened_tables:表示累計已經打開的表數目。
那麼如何判斷table_cache是否設置合理呢?其判斷尺度以下:
若是Opened_tables遠大於Open_tables,而且Open_tables很接近table_cache,那麼就說明table_cache偏小。
還要注意設置操做系統的參數,由於即使你把table_cache設置得很大,一旦超過了操做系統的限制也沒用,能夠按以下方法查詢當前值:
ulimit -n
設置方法也很簡單,好比設置成8k,能夠這樣:
vi /etc/security/limits.conf
* hard nofile 8192
* soft nofile 8192
這樣設定比在/etc/rc.local裏設定ulimit -n 8192更合理一些(參考連接)。
MySQL運行穩定後,查看open_files_limit參數:
mysql> show variables like '%open%';
在大量使用MyISAM的環境裏,應該保證open_files_limit表類型至少是table_cache的二到三倍,這是由於每一個MyISAM表都包括三個文件:一個表定義文件,一個表索引文件,一個表數據文件,詳細介紹能夠參考文檔。而在Innodb的環境裏,一個表只有一個文件,明白這些基本知識對解決問題頗有幫助。
具體的數據庫文件打開狀況能夠用lsof來查看:
lsof | grep MYI 或者 lsof | grep MYD
能夠發現索引文件描述符是客戶端共享的,數據文件則不是,你能夠這樣確認這一點:
lsof | egrep -i 'myd|myi' | awk '{++state[$NF]} END {for(key in state) print state[key], "\t", key}' | sort -nr
爲了保險點,或許還要查查內核的相關參數,好比fs.file-max,這些細節每每會影響到MySQL:
sysctl -a | grep "file"
注意到以上這些因素,問題差很少就能解決了。不過還要注意一點,table cache不是越大越好:
http://www.freshbooks.com/blog/2008/09/09/now-were-flying/
http://www.mysqlperformanceblog.com/2009/11/16/table_cache-negative-scalability/
http://www.mysqlperformanceblog.com/2009/11/26/more-on-table_cache/
BTW:若是你比較懶惰,也能夠用MySQL Performance Tuning Primer Script來判斷參數是否合理mysql
在咱們的意識裏,一般增大table_cache,儘可能使打開的表句柄在緩存中,mysql能更快地響應操做,可是當我增大table_cache後,cpu增大了不少,查資料發現,table_cache並非越大越好,由於mysql只有一個全局鎖來控制打開和關閉表,也就是說不管有多少個線程在並行執行,只有一個線程能夠打開或關閉表,這也就會出現不少死鎖,別的線程等待那個全局鎖,相應地增長了cpu的消耗,延長了其餘連接線程執行sql的時間,下降系統性能,因此在保證table_cache夠用的狀況下,儘可能保持table_cache足夠小,可是這個度怎麼把握,我也沒有必定的尺度,還得再學習。sql
參考資料:數據庫
咱們跑的飛快post