• MySQL open_files_limit 设置【转】


    查看Mysqld 进程打开的文件描述符的数量:

    root@pts/0 # pidof mysqld
    7668 6539

    root@pts/0 # lsof -p 7668 | grep -E 'MYD|MYI'  #查看打开的表
    mysqld 7668 mysql 22u REG 8,3 2048 16252958 /data1/db3306/mysql/user.MYI
    mysqld 7668 mysql 23u REG 8,3 556 16252961 /data1/db3306/mysql/user.MYD
    mysqld 7668 mysql 24u REG 8,3 5120 16252953 /data1/db3306/mysql/db.MYI
    mysqld 7668 mysql 25u REG 8,3 880 16252956 /data1/db3306/mysql/db.MYD
    mysqld 7668 mysql 26u REG 8,3 5120 16253097 /data1/db3306/mysql/proxies_priv.MYI
    mysqld 7668 mysql 27u REG 8,3 1386 16253098 /data1/db3306/mysql/proxies_priv.MYD
    mysqld 7668 mysql 28u REG 8,3 4096 16252976 /data1/db3306/mysql/tables_priv.MYI
    mysqld 7668 mysql 29u REG 8,3 0 16252977 /data1/db3306/mysql/tables_priv.MYD
    mysqld 7668 mysql 30u REG 8,3 4096 16252979 /data1/db3306/mysql/columns_priv.MYI
    mysqld 7668 mysql 31u REG 8,3 0 16252980 /data1/db3306/mysql/columns_priv.MYD
    mysqld 7668 mysql 32u REG 8,3 4096 16253016 /data1/db3306/mysql/procs_priv.MYI
    mysqld 7668 mysql 33u REG 8,3 0 16253017 /data1/db3306/mysql/procs_priv.MYD
    mysqld 7668 mysql 34u REG 8,3 1024 16252973 /data1/db3306/mysql/servers.MYI
    mysqld 7668 mysql 35u REG 8,3 0 16252974 /data1/db3306/mysql/servers.MYD
    mysqld 7668 mysql 36u REG 8,3 2048 16253025 /data1/db3306/mysql/event.MYI
    mysqld 7668 mysql 37u REG 8,3 0 16253026 /data1/db3306/mysql/event.MYD

    root@pts/0 # cat /proc/7668/limits   #查看mysqld 资源的限制
    Limit Soft Limit Hard Limit Units
    Max cpu time unlimited unlimited seconds
    Max file size unlimited unlimited bytes
    Max data size unlimited unlimited bytes
    Max stack size 10485760 unlimited bytes
    Max core file size 0 unlimited bytes
    Max resident set unlimited unlimited bytes
    Max processes 65535 65535 processes
    Max open files 65505 65505 files
    Max locked memory 65536 65536 bytes
    Max address space unlimited unlimited bytes
    Max file locks unlimited unlimited locks
    Max pending signals 1032031 1032031 signals
    Max msgqueue size 819200 819200 bytes
    Max nice priority 0 0
    Max realtime priority 0 0

    背景:     
    数据库链接不上,报错:

    root@localhost:/var/log/mysql# mysql -uzjy -p -h192.168.1.111 --default-character-set=utf8 -P3306
    Enter password: 
    ERROR 2013 (HY000): Lost connection to MySQL server at 'reading initial communication packet', system error: 0

    分析方法:
    在这个地方我看不出什么,直接看错误日志:

    [ERROR] /usr/sbin/mysqld: Can't open file: './java/tt_fte.frm' (errno: 24)
    root@localhost:/var/log/mysql# perror 24
    OS error code  24:  Too many open files

    一看到这里,就觉得需要调整 open_files_limit 参数了(默认最小1024),至此问题解决。虽然问题解决了,但是还没有弄清楚MySQL打开了多少个文件描述符,打开了哪写文件描述符号,以及如何预防。怎么了解MySQL打开了多少个文件描述符呢?
    知识点:lsof去查看,理解myisam和innodb的文件描述符、OS 的ulimit相关认识。
    基于上面的问题,现在来分析(此时数据库就连不上了,一直报无法打开的错误信息)查看MySQL打开的文件:

    复制代码
    root@localhost:~# lsof -p 26288 | wc -l
    1042
    
    #因为数据库链接不了,所以只能通过系统查看他的文件描述符
    root@localhost:~# cat /proc/26288/limits 
    Limit                     Soft Limit           Hard Limit           Units     
    Max cpu time              unlimited            unlimited            seconds   
    Max file size             unlimited            unlimited            bytes     
    Max data size             unlimited            unlimited            bytes     
    Max stack size            8388608              unlimited            bytes     
    Max core file size        0                    unlimited            bytes     
    Max resident set          unlimited            unlimited            bytes     
    Max processes             79877                79877                processes 
    Max open files            1024                 4096                 files     
    Max locked memory         65536                65536                bytes     
    Max address space         unlimited            unlimited            bytes     
    Max file locks            unlimited            unlimited            locks     
    Max pending signals       79877                79877                signals   
    Max msgqueue size         819200               819200               bytes     
    Max nice priority         0                    0                    
    Max realtime priority     0                    0                    
    Max realtime timeout      unlimited            unlimited            us   

    也可以通过下面的方法查看,下面的方法最为精确
    root@localhost:~# ls -lh /proc/26288/fd | wc -l
    1024
    复制代码

    上面看出,MySQL这时打开的文件描述符1024,已经达到上限,所以再打开的时候就报错了。修改open_files_limit 参数,设置为2000试试?

    复制代码
    root@localhost:~# lsof -p 27732 | wc -l
    1053
    root@localhost:~# cat /proc/27732/limits 
    Limit                     Soft Limit           Hard Limit           Units     
    Max cpu time              unlimited            unlimited            seconds   
    Max file size             unlimited            unlimited            bytes     
    Max data size             unlimited            unlimited            bytes     
    Max stack size            8388608              unlimited            bytes     
    Max core file size        0                    unlimited            bytes     
    Max resident set          unlimited            unlimited            bytes     
    Max processes             79877                79877                processes 
    Max open files            2000                 2000                 files     
    Max locked memory         65536                65536                bytes     
    Max address space         unlimited            unlimited            bytes     
    Max file locks            unlimited            unlimited            locks     
    Max pending signals       79877                79877                signals   
    Max msgqueue size         819200               819200               bytes     
    Max nice priority         0                    0                    
    Max realtime priority     0                    0                    
    Max realtime timeout      unlimited            unlimited            us        
    root@localhost:~# ls -lh /proc/27732/fd | wc -l
    1035
    复制代码

    上面看出,MySQL需要打开的文件描述符1035,小于2000,数据库正常。到此为止,上面的问题得到解决。想更清楚了解的请继续看:
    查看数据库的变量:

    复制代码
    zjy@localhost : (none) 10:27:19>show global status like 'open%';
    +--------------------------+-------+
    | Variable_name            | Value |
    +--------------------------+-------+
    | Open_files               | 804   |
    | Open_streams             | 0     |
    | Open_table_definitions   | 400   |
    | Open_tables              | 400   |
    | Opened_files             | 6803  |
    | Opened_table_definitions | 3861  |
    | Opened_tables            | 4315  |
    +--------------------------+-------+
    7 rows in set (0.00 sec)
    
    zjy@localhost : (none) 10:31:11>show global variables like 'open%';
    +------------------+-------+
    | Variable_name    | Value |
    +------------------+-------+
    | open_files_limit | 2000  |
    +------------------+-------+
    1 row in set (0.00 sec)
    
    zjy@localhost : (none) 10:39:03>show global variables like 'table_open_cache';
    +------------------+-------+
    | Variable_name    | Value |
    +------------------+-------+
    | table_open_cache | 400   |
    +------------------+-------+
    1 row in set (0.00 sec)
    复制代码

    在MySQL 5.1.3之后,还添加了2个状态值:Open_table_definitions和Opened_table_definitions。这2个值代表的意思如下:
    Open_table_definitions  :代表当前缓存了多少.frm文件。
    Opened_table_definitions:代表自从MySQL启动后,缓存了.frm文件的数量。 需要注意的是.frm文件是MySQL用于存放表结构的文件,对应myisam和innodb存储引擎都必须有的,可以通过show open tables 查看 这2个变量的值。

    说到这里主要关注的参数还是:table_open_cache 其作用是:从MySQL5.1.3 开始改为table_open_cache,所有线程所打开表的数量, 增加此值就增加了mysqld所需要的文件描述符的数量.它的作用就是缓存表文件描述符,降低打开关闭表的频率, 如果这个参数设置得过小,那么很快就会被占满,再有新请求过来的时候,就不得不关闭一些已打开的表以便为新请求腾出空间,从而出现频繁的打开关闭MyISAM表文件的情况,而INNODB表的打开 不受这个参数控制,而是放到其数据字典当中,即在ibd中

    查看打开的各个文件描述符是什么:大部分都是MYI,MYD,IBD文件。

    复制代码
    root@localhost:/proc/27732/fd# ls -lh | grep MYI | wc -l
    400
    root@localhost:/proc/27732/fd# ls -lh | grep MYD | wc -l
    400
    root@localhost:/proc/27732/fd# ls -lh | grep ibd | wc -l
    215
    root@localhost:/proc/27732/fd# lsof | grep /var/lib/mysql | grep MYI | wc -l
    400
    root@localhost:/proc/27732/fd# lsof | grep /var/lib/mysql | grep MYD | wc -l
    400
    root@localhost:/proc/27732/fd# lsof | grep /var/lib/mysql | grep '.ibd' | wc -l
    214
    复制代码

    上面看到400,是否和table_open_cache有关?经过测试得出:MySQL变量 Open_tables 打开了 table_open_cache的数目,和lsof中的MYI和MYD数目对应(MYISAM)。
    即  Open_tables  <=  table_open_cache要是Open_tables 和 table_open_cache 一样,表示MySQL已经用完了表缓存,可以适当的调大。
    214是什么意思?是不是INNODB表?经验证确认:

    复制代码
    zjy@localhost : (none) 10:43:54>select count(*) from information_schema.tables where ENGINE='innodb';
    +----------+
    | count(*) |
    +----------+
    |      214 |
    +----------+
    1 row in set (0.05 sec)
    复制代码

    从上面的信息中得出:

    open_files_limit = table_open_cache*2 + innodb表

    把上面的数字带进去:

    open_files_limit = 400*2 + 214 = 1014 

    结果为1014 要小于默认的1024,为什么默认时候1024报错呢,那除这些外还包含什么?

    root@localhost:/proc/27732/fd# ls -lh | grep -v  MYI | grep -v MYD | grep -v ".ibd" | wc -l 
    23
    #注意这个出现的数目不是固定的,有随机性。包含了各种日志、共享表空间、socket文件等信息。
    View Code
    root@localhost:/proc/27732/fd# ls -lh | grep -v  MYI | grep -v MYD | grep -v ".ibd"
    total 0
    lrwx------ 1 root root 64 Jan 30 22:29 0 -> /dev/null
    l-wx------ 1 root root 64 Jan 30 22:29 1 -> /var/log/mysql/mysql.err
    lrwx------ 1 root root 64 Jan 30 22:29 10 -> socket:[795955]
    lrwx------ 1 root root 64 Jan 30 22:29 11 -> /tmp/ibKm37iF (deleted)
    lrwx------ 1 root root 64 Jan 30 22:29 12 -> socket:[795956]
    lrwx------ 1 root root 64 Jan 30 22:29 13 -> socket:[800403]
    lrwx------ 1 root root 64 Jan 30 22:29 17 -> /var/lib/lxc/localhost/rootfs.hold
    l-wx------ 1 root root 64 Jan 30 22:29 2 -> /var/log/mysql/mysql.err
    lrwx------ 1 root root 64 Jan 30 22:29 3 -> /var/lib/mysql/ibdata1
    lrwx------ 1 root root 64 Jan 30 22:29 31 -> /var/lib/mysql/master.info
    lrwx------ 1 root root 64 Jan 30 22:29 32 -> /var/lib/mysql/mysqld-relay-bin.index
    lrwx------ 1 root root 64 Jan 30 22:29 33 -> /var/lib/mysql/relay-log.info
    lrwx------ 1 root root 64 Jan 30 22:29 34 -> /var/lib/mysql/mysqld-relay-bin.000123
    lrwx------ 1 root root 64 Jan 30 22:29 37 -> socket:[795961]
    lrwx------ 1 root root 64 Jan 30 22:29 4 -> /tmp/ibse5AFw (deleted)
    lrwx------ 1 root root 64 Jan 30 22:29 5 -> /tmp/ibBAQlVN (deleted)
    lrwx------ 1 root root 64 Jan 30 22:29 6 -> /tmp/ibxpP6a5 (deleted)
    lrwx------ 1 root root 64 Jan 30 22:39 624 -> socket:[800541]
    lrwx------ 1 root root 64 Jan 30 22:39 625 -> socket:[800542]
    lrwx------ 1 root root 64 Jan 30 22:29 7 -> /tmp/ib9dUH3m (deleted)
    lrwx------ 1 root root 64 Jan 30 22:29 8 -> /var/lib/mysql/ib_logfile0
    lrwx------ 1 root root 64 Jan 30 22:29 9 -> /var/lib/mysql/ib_logfile1

    最后结果:

    open_files = 400*2 + 214 + 23(随机) = 1037

    得到了最后的打开文件描述符的结果为1037,那把 open_files_limit 设置成1037看看会是什么情况?理论上不能创建表了,重启之后但是数据库正常,那创建一张INNODB表试试?
    可以创建4张表,(和上面说的随机性有关系,因为此时的数据不是23了。)到创建第5张表的时候:

    zjy@localhost : zhoujy 11:03:24>create table idx_mer5(id int,name varchar(10),name1 varchar(10),address varchar(30))engine =innodb;
    ERROR 23 (HY000): Out of resources when opening file './zhoujy/' (Errcode: 24)

    数据库直接报错,无法创建表,此时重启数据库,又会出现和本文开头的错误信息,因为此时会多了(ls -lh | grep -v  MYI | grep -v MYD | grep -v CSV | grep -v ".ibd")的内容。找到问题出现的原因了。解决办法是:
    1,在不修改open_files_limit下把table_open_cache参数调小。

    2,修改open_files_limit,至少设置成上面的这个公式。

    总结:

    在Mysql数据库中,想知道Mysql打开了多少张表,用:

    复制代码
    root@localhost >show global status like 'open%';
    +--------------------------+-------+
    | Variable_name            | Value |
    +--------------------------+-------+
    | Open_files               | 351   |
    | Open_streams             | 0     |
    | Open_table_definitions   | 305   |
    | Open_tables              | 305   |
    | Opened_files             | 996   |
    | Opened_table_definitions | 403   |
    | Opened_tables            | 1227  |
    +--------------------------+-------+
    7 rows in set (0.00 sec)

    具体打开了哪些表:
    root@localhost >show open tables;
    复制代码

     打开了多少文件描述符,用:

    复制代码
    root@zhoujy:~# pidof mysqld
    19068
    root@zhoujy:~# cd /proc/19068/fd
    #总的文件描述符: root@zhoujy:
    /proc/19068/fd# ls -lh | wc -l 498 #MyISAM描述符: root@zhoujy:/proc/19068/fd# ls -lh | grep 'MYD' | wc -l 172 #CSV描述符: root@zhoujy:/proc/19068/fd# ls -lh | grep 'CSV' | wc -l 2 #Innodb描述符: root@zhoujy:/proc/19068/fd# ls -lh | grep '.ibd' | wc -l 131

    要是此时的【
    文件描述符】的总数 和 open_files_limit 一样,在新建表的时候就会导致数据库报打不开表的错误信息。
    复制代码

    知识点:

           MyISAM和CSV表打开时占用2个文件描述符,Innodb则需要1个文件描述符。一些日志信息(relay log,binlog,error-log等)也需要文件描述符。table_open_cache对MyISAM有效,对Innodb无效。当运行 flush tables 关闭表的时候,只对MyISAM表有效,即关闭MISAM表的文件描述符,Innodb表也会关闭,但是文件描述符不会关。
           当表都是MyISAM,在极端的情况下,table_open_cache数目的表全部被打开(512张)就会占用掉1024个文件描述符。而open_files_limit是1024的话,就会出现报错的情况(本文例子的情况)。所以
    如果是有大量的 MyISAM 表,那么就需要特别注意打开文件数是否会超出限制了。
           总之,确实设置open_files_limit的时候,先要知道table_open_cache 为多少,再加上inodb表的数目和一些日志的数目。
    上面的结果和系统的ulimit没有关系(ubuntu默认apt下来的实例),要是不是默认安装的实例呢?请继续看:
           在测试中发现,设置OS的文件描述符(/etc/security/limits.conf)
    值是无效的,即MySQL启动后open_files_limit始终以my.cnf中设置的参数open_files_limit为准。(版本MySQL5.5.29 ubuntu0.12.04.1),而在非Ubuntu中是按照他们(os和mysql)哪个最高用哪个的方法,通过 cat /proc/10415/limits 查看,依然都是数据库配置文件(open_files_limit)中设置的值。怀疑是ubuntu定制mysql的问题(apt下来的mysql)

    而用mysqld_safe开启的实例(非apt-get install 安装),则按照下面的规则:

    复制代码
    默认设置的open_files_limit 比其他相关的参数都大。[max_connections*5和10+max_connections+table_cache_size*2 大]
    
    一:
    1:ulimit -n 65535
    2:修改 my.cnf 限制
    open_files_limit = 10000
    3:重启 mysql
    4:show global variables like '%open%';
    | open_files_limit | 10000 |
    
    二:
    注释 open_files_limit
    | open_files_limit | 65535 
    
    三:
    1:ulimit -n 5000
    2:修改 my.cnf 限制
    open_files_limit = 10000
    3:重启 mysql
    4:show global variables like '%open%';
    | open_files_limit | 10000 
    
    四:
    注释 open_files_limit
    | open_files_limit | 5000 

    这里总结一句话:当open_files_limit没有被配置的时候,比较max_connections*5和ulimit -n的值,哪个大用哪个,当open_file_limit被配置的时候,
    比较open_files_limit
    和max_connections*5的值,哪个大用哪个。
    复制代码

     注意:open_files_limit 大小和 max_connections*5需要比较,那个最大就用那个值来设置open_files_limit 。【比较open_files_limit,max_connections*5和10+max_connections+table_cache_size*2中最大值】

    复制代码
    --my.cnf--
    open_files_limit = 5000
    max_connections = 1024
    
    mysql> show global  variables like '%open%';
    +-------------------+----------+
    | Variable_name     | Value    |
    +-------------------+----------+
    | open_files_limit  | 5120     |   #1024*5 > 5000
    +-------------------+----------+
    复制代码
    View Code
    vi /etc/security/limits.conf
    
    mysql            soft    nofile          65536
    mysql            hard    nofile          65536

    总结:
          
    所以在配置open_files_limit的时候,设置多大合适,需要知道具体的表数目和类型等,具体情况需要自己分析。没有配置的则需要注意配置OS的ulimit(启动前设置)和max_connections的大小。而用apt-get 下来的mysql实例则都是按照open_files_limit和max_connections 来比较设置的,和OS的ulimit无关。

    ########2016-08-12更新########

    怎么计算打开文件数

    ########2016-08-12更新########

    相关资料:

    Mysql如何打开文件数
    MySQL打开的文件描述符限制
    关于table cache的相关参数

  • 相关阅读:
    Java学习
    Java学习
    Vue.js学习(十五)—— ref和$refs的使用
    Vue.js学习(十四)—— Vue中的导航守卫(路由守卫)
    Vue.js学习(十二)—— Vue 全局挂载自定义函数
    Vue.js学习(十一)—— 项目开始、首页入门(main.js)
    Vue.js学习(十)—— element-ui 实战各种小技巧(长期更新)(转)
    Vue.js学习(九)—— normalize.css在vue中使用
    Vue.js学习(七)—— Vue开发与调试工具之vscode
    Vue.js学习(六)—— 轻量级JS Cookie插件
  • 原文地址:https://www.cnblogs.com/mao3714/p/8777824.html
Copyright © 2020-2023  润新知