来源: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