You are on page 1of 4

mysql 如何计算打开文件数

从手册的"6.4.8. How MySQL Opens and Closes Tables"可以了解到,每打开一个 MyISAM 表,就需要

使用 2 个文件描述符,咱们来验证一下。

1. 重启 mysqld
/etc/init.d/mysql restart

2. 看看打开了几个文件
lsof | grep /home/mysql
...
mysqld 24349 mysql 5u unix 0x000001041e8de040 4244009
/home/mysql/mysql.sock
mysqld 24349 mysql 6u REG 8,33 2048 30425188
/home/mysql/mysql/host.MYI
mysqld 24349 mysql 7u REG 8,33 0 30425189
/home/mysql/mysql/host.MYD
mysqld 24349 mysql 8u REG 8,33 2048 30425153
/home/mysql/mysql/user.MYI
mysqld 24349 mysql 9u REG 8,33 892 30425155
/home/mysql/mysql/user.MYD
mysqld 24349 mysql 10u REG 8,33 5120 30425126
/home/mysql/mysql/db.MYI
mysqld 24349 mysql 11u REG 8,33 3080 30425148
/home/mysql/mysql/db.MYD
mysqld 24349 mysql 12u REG 8,33 4096 30425154
/home/mysql/mysql/tables_priv.MYI
mysqld 24349 mysql 13u REG 8,33 0 30425157
/home/mysql/mysql/tables_priv.MYD
mysqld 24349 mysql 14u REG 8,33 4096 30425143
/home/mysql/mysql/columns_priv.MYI
mysqld 24349 mysql 15u REG 8,33 0 30425156
/home/mysql/mysql/columns_priv.MYD
mysqld 24349 mysql 16u REG 8,33 4096 30425127
/home/mysql/mysql/procs_priv.MYI
mysqld 24349 mysql 17u REG 8,33 0 30425136
/home/mysql/mysql/procs_priv.MYD
mysqld 24349 mysql 18u REG 8,33 1024 30425173
/home/mysql/mysql/servers.MYI
mysqld 24349 mysql 19u REG 8,33 0 30425174
/home/mysql/mysql/servers.MYD
mysqld 24349 mysql 20u REG 8,33 2048 30425182
/home/mysql/mysql/event.MYI
mysqld 24349 mysql 21u REG 8,33 0 30425183
/home/mysql/mysql/event.MYD
...

可以看到,总共打开了 8 个表,每个表分别有 2 个文件描述符,看来没错。

3. 再来看 status 结果
mysql>show global status like 'open_%';
+------------------------+-------+
| Variable_name | Value |
+------------------------+-------+
| Open_files | 17 |
| Open_streams | 0 |
| Open_table_definitions | 15 |
| Open_tables | 8 |
| Opened_files | 52 |
| Opened_tables | 15 |
+------------------------+-------+

4. flush tables 后再看看


mysql>flush tables;

mysql> show global status like 'open_%';


+------------------------+-------+
| Variable_name | Value |
+------------------------+-------+
| Open_files | 1 |
| Open_streams | 0 |
| Open_table_definitions | 0 |
| Open_tables | 0 |
| Opened_files | 52 |
| Opened_tables | 15 |
+------------------------+-------+

lsof | grep /home/mysql


...
mysqld 24349 mysql 5u unix 0x000001041e8de040 4244009
/home/mysql/mysql.sock
mysqld 24349 mysql 22u unix 0x00000102378ff980 4244128
/home/mysql/mysql.sock
...

可以看到,flush 之后,所有的文件描述符都释放了。

通过测试可以得知,另一个打开的文件描述符是 slow query log 所用。

如果启用了 innodb,则还会打开 ibdata*, ib_logfile* 等文件,不过这些文件并没有放到

table_cache 中,因此每次看 statu 时,Open_files 没有增加,Opened_files 则增加了。

如果是有大量的 MyISAM 表,那么就需要特别注意打开文件数是否会超出限制了。

接下来仔细了解下这个最大文件数相关的参数:

table_cache (新版本改成了 table_open_cache) The number of cached open tables.


open_files_limit If this is not 0, then mysqld will use this value to reserve
file descriptors to use with setrlimit(). If this value is 0 then mysqld will
reserve max_connections*5 or max_connections + table_cache*2 (whichever is larger)
number of files.
如果 open_files_limit 不是设置为 0,则以 setrlimit() 函数计算后的结果为准,如果设置为 0,则

实际值是 max_connections*5 或 max_connections + table_cache*2 中的最大者。

因此,想要解决打开文件数超限的问题,还需要综合系统内核限制(ulimit -n),mysqld 自身限制

(open_files_limit),以及表缓存数(table_open_cache)等多方面因素。

不过,实际测试中,发现却不是这样的,open_files_limit 采用了内核的最大限制,而非上面的计算结果。
ulimit -n
65535

vi /etc/my.cnf
...
open_files_limit = 10000
...

/etc/init.d/mysql restart

mysql>show global variables like '%open%';


| open_files_limit | 65535 |
| table_open_cache | 1000 |

vi /etc/my.cnf
...
#open_files_limit = 10000
...

/etc/init.d/mysql restart

mysql>show global variables like '%open%';


| open_files_limit | 65535 |
| table_open_cache | 1000 |

而这个时候,按计算公式结果如下:
| max_connections | 100 |
| table_open_cache | 1000 |

max_open_files_1 = max_connections + table_cache * 2 = 100 + 1000 * 2 = 2100


max_open_files_2 = max_connections*5 = 100 * 5 = 500

修改 ulimit 试试看:
unlimit -n 5000

vi /etc/my.cnf
...
open_files_limit = 10000
...

/etc/init.d/mysql restart

mysql>show global variables like '%open%';


| open_files_limit | 10000 |
| table_open_cache | 1000 |

vi /etc/my.cnf
...
#open_files_limit = 10000
...

/etc/init.d/mysql restart

mysql>show global variables like '%open%';


| open_files_limit | 5000 |
| table_open_cache | 1000 |

看到了吧,结果完全跟文档描述的以及 mysql 源码中写的不一样,看来预编译版本有些地方不太可靠啊 :(

以上测试在 mysql 5.1.23-rc 以及 5.0.45 均一样。

./configure --prefix=/usr/local/mysql5124 \
--with-extra-charsets=complex --enable-thread-safe-client \
--enable-local-infile --localstatedir=/home/mysql --
libexecdir=/usr/local/mysql5124/bin/ \
--disable-shared --with-embedded-server --with-innodb --with-client-ldflags=-all-
static --with-mysqld-ldflags=-all-static

http://you.video.sina.com.cn/b/12417440-1401913474.html

http://bbs.auto.sohu.com/r-xuec-168862-0-0-0.html