暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

MySQL的open_file_limit配置迷雾

沃趣技术 2019-11-29
395

作者:魏新平,知数堂第5期MySQL实战班学员,第10期MySQL优化班学员,现任职助教。

文章来源:知数堂


一、官方解释

mysqld进程能使用的最大文件描述符数量,mysql实际的取值会从下面四个值当中获取最大的。

1) 10 + maxconnections + (tableopen_cache * 2)

2) max_connections * 5

3) operating system limit if positive

4) if operating system limit is Infinity:

open_files_limit value specified at startup, 5000 if none

我们接下来测试让mysql分别取上面四种值为实际的取值。

二、测试mysql版本和系统版本

操作系统版本为CentOS Linux release 7.4.1708 (Core),全新安装,没有任何配置。
mysql版本 Percona-Server-5.7.21-20-Linux.x86_64
接下来开始测试了。

没有配置open_files_limit参数(root用户登陆操作)

mysql配置文件如下:
  1. [mysqld]

  2. user = mysql

  3. port = 5721

  4. socket = tmp/mysql_sandbox5721.sock

  5. basedir = root/opt/mysql/5.7.21

  6. datadir = opt/msb_5_7_21/data

  7. tmpdir = /opt/msb_5_7_21/tmp

  8. pid-file = /opt/msb_5_7_21/data/mysql_sandbox5721.pid

  9. bind-address = 127.0.0.1

table_open_cache默认值是2000,max_connections默认值是151+1,因为还有一个extra_max_connections,ulimit -n 的值为1024。
结果如下:
  1. [root@mysqlmaster ~]# ps -ef | grep mysqld

  2. root 30471009:52 pts/200:00:00/bin/sh bin/mysqld_safe --defaults-file=/opt/msb_5_7_21/my.sandbox.cnf

  3. mysql 32533047009:52 pts/200:00:02/root/opt/mysql/5.7.21/bin/mysqld --defaults-file=/opt/msb_5_7_21/my.sandbox.cnf --basedir=/root/opt/mysql/5.7.21--datadir=/opt/msb_5_7_21/data --plugin-dir=/root/opt/mysql/5.7.21/lib/mysql/plugin --user=mysql --log-error=/opt/msb_5_7_21/data/msandbox.err --pid-file=/opt/msb_5_7_21/data/mysql_sandbox5721.pid --socket=/tmp/mysql_sandbox5721.sock --port=5721

  4. root 105835177009:57 pts/400:00:00 grep --color=auto mysqld

  5. [root@mysqlmaster ~]# cat /proc/3253/limits |grep files

  6. Max open files 50005000 files

  7. --------------------------------------------------------------------------------

  8. mysql [localhost:5721] {root} ((none)) > SELECT @@open_files_limit;

  9. +--------------------+

  10. | @@open_files_limit|

  11. +--------------------+

  12. | 5000|

  13. +--------------------+

  14. 1 row inset(0.00 sec)

不管是系统层面还是mysql,取值都是5000,符合了第四种情况。

4) if operating system limit is Infinity:

openfileslimit value specified at startup, 5000 if none

其他几种公式的值为:
1. select @@max_connections + @@extra_max_connections + 10 + @@table_open_cache*2 = 4162
2. select (@@max_connections+@@extra_max_connections)*5 = 760
3. ulimit -n = 1024
那我们接下来依次增大其他几种公式的值,看看结果会有什么变化。
10 + maxconnections + (tableopen_cache * 2)最大
设置table_open_cache=3000,其他不变,取值如下:
1. select @@max_connections + @@extra_max_connections + 10 + @@table_open_cache*2 = 6162
2. select (@@max_connections+@@extra_max_connections)*5 = 760
3. ulimit -n = 1024
4. 5000
结果为:
  1. [root@mysqlmaster msb_5_7_21]# ps -ef | grep mysqld

  2. root 800091010:43 pts/200:00:00/bin/sh bin/mysqld_safe --defaults-file=/opt/msb_5_7_21/my.sandbox.cnf

  3. mysql 80227800091110:43 pts/200:00:01/root/opt/mysql/5.7.21/bin/mysqld --defaults-file=/opt/msb_5_7_21/my.sandbox.cnf --basedir=/root/opt/mysql/5.7.21--datadir=/opt/msb_5_7_21/data --plugin-dir=/root/opt/mysql/5.7.21/lib/mysql/plugin --user=mysql --log-error=/opt/msb_5_7_21/data/msandbox.err --pid-file=/opt/msb_5_7_21/data/mysql_sandbox5721.pid --socket=/tmp/mysql_sandbox5721.sock --port=5721

  4. root 805551129010:43 pts/200:00:00 grep --color=auto mysqld

  5. [root@mysqlmaster msb_5_7_21]#

  6. [root@mysqlmaster msb_5_7_21]# cat /proc/80227/limits |grep files

  7. Max open files 61626162 files

  8. ------------------------------------------------------------------------------------------------

  9. mysql [localhost:5721] {root} ((none)) > SELECT @@open_files_limit;

  10. +--------------------+

  11. | @@open_files_limit|

  12. +--------------------+

  13. | 6162|

  14. +--------------------+

  15. 1 row inset(0.00 sec)

max_connections * 5最大
设置max_connections的值为2000,其他值默认,取值如下:
1. select @@max_connections + @@extra_max_connections + 10 + @@table_open_cache*2 =6011
2. select (@@max_connections+@@extra_max_connections)*5 = 10005
3. ulimit -n = 1024
4. 5000
结果如下:
  1. [root@mysqlmaster msb_5_7_21]# ps -ef | grep mysqld

  2. root 879141010:48 pts/200:00:00/bin/sh bin/mysqld_safe --defaults-file=/opt/msb_5_7_21/my.sandbox.cnf

  3. mysql 88132879142110:48 pts/200:00:01/root/opt/mysql/5.7.21/bin/mysqld --defaults-file=/opt/msb_5_7_21/my.sandbox.cnf --basedir=/root/opt/mysql/5.7.21--datadir=/opt/msb_5_7_21/data --plugin-dir=/root/opt/mysql/5.7.21/lib/mysql/plugin --user=mysql --log-error=/opt/msb_5_7_21/data/msandbox.err --pid-file=/opt/msb_5_7_21/data/mysql_sandbox5721.pid --socket=/tmp/mysql_sandbox5721.sock --port=5721

  4. root 883001129010:48 pts/200:00:00 grep --color=auto mysqld

  5. [root@mysqlmaster msb_5_7_21]# cat /proc/88132/limits | grep files

  6. Max open files 1000510005 files

  7. ----------------------------------------------------------------------------------------------

  8. mysql [localhost:5721] {root} ((none)) > SELECT @@open_files_limit;

  9. +--------------------+

  10. | @@open_files_limit|

  11. +--------------------+

  12. | 10005|

  13. +--------------------+

  14. 1 row inset(0.00 sec)

operating system limit if positive最大
我的理解是ulimit -n显示的值。max_connections和table_open_cache取默认值,然后ulimit -n 6000。重启mysql。
公式取值如下:
1. select @@max_connections + @@extra_max_connections + 10 + @@table_open_cache*2 = 4162
2. select (@@max_connections+@@extra_max_connections)*5 = 760
3. ulimit -n = 6000
结果如下:
  1. [root@mysqlmaster msb_5_7_21]# ps -ef | grep mysql

  2. root 938251010:52 pts/200:00:00/bin/sh bin/mysqld_safe --defaults-file=/opt/msb_5_7_21/my.sandbox.cnf

  3. mysql 94031938251610:52 pts/200:00:01/root/opt/mysql/5.7.21/bin/mysqld --defaults-file=/opt/msb_5_7_21/my.sandbox.cnf --basedir=/root/opt/mysql/5.7.21--datadir=/opt/msb_5_7_21/data --plugin-dir=/root/opt/mysql/5.7.21/lib/mysql/plugin --user=mysql --log-error=/opt/msb_5_7_21/data/msandbox.err --pid-file=/opt/msb_5_7_21/data/mysql_sandbox5721.pid --socket=/tmp/mysql_sandbox5721.sock --port=5721

  4. root 942541129010:52 pts/200:00:00 grep --color=auto mysql

  5. [root@mysqlmaster msb_5_7_21]# cat /proc/94031/limits | grep files

  6. Max open files 60006000 files

  7. ---------------------------------------------------------------------------------------

  8. mysql [localhost:5721] {root} ((none)) > SELECT @@open_files_limit;

  9. +--------------------+

  10. | @@open_files_limit|

  11. +--------------------+

  12. | 6000|

  13. +--------------------+

  14. 1 row inset(0.00 sec)

三、配置open_files_limit参数(root用户登陆操作)

配置了open_files_limit参数,还是会取最大值。但是不一样的是第三种公式的取值,也就是ulimit -n不会被考虑进来。而是从另外三种取值当中获取最大的值。
执行ulimit -n 6000 增大限制,然后max_connections,table_open_cache都是默认。open_files_limit设置为4200。重启mysql
结果如下:
  1. [root@mysqlmaster msb_5_7_21]# ps -ef | grep mysqld

  2. root 1040481010:58 pts/200:00:00/bin/sh bin/mysqld_safe --defaults-file=/opt/msb_5_7_21/my.sandbox.cnf

  3. mysql 1042691040481910:58 pts/200:00:01/root/opt/mysql/5.7.21/bin/mysqld --defaults-file=/opt/msb_5_7_21/my.sandbox.cnf --basedir=/root/opt/mysql/5.7.21--datadir=/opt/msb_5_7_21/data --plugin-dir=/root/opt/mysql/5.7.21/lib/mysql/plugin --user=mysql --log-error=/opt/msb_5_7_21/data/msandbox.err --open-files-limit=4200--pid-file=/opt/msb_5_7_21/data/mysql_sandbox5721.pid --socket=/tmp/mysql_sandbox5721.sock --port=5721

  4. root 1044601129010:58 pts/200:00:00 grep --color=auto mysqld

  5. [root@mysqlmaster msb_5_7_21]# cat /proc/104269/limits | grep files

  6. Max open files 42004200 files

  7. ------------------------------------------------------------------

  8. mysql [localhost:5721] {root} ((none)) > SELECT @@open_files_limit;

  9. +--------------------+

  10. | @@open_files_limit|

  11. +--------------------+

  12. | 4200|

  13. +--------------------+

  14. 1 row inset(0.00 sec)

显示的值就变成了4200,明显6000没有被考虑进来,就算是值比4200大。其他的情况和没有配置open_files_limit相同,获取最大的值,篇幅原因就不做赘述了。

四、总结

在没有配置的open_files_limit的情况下,会获取下面公式的最大值。

1) 10 + maxconnections + (tableopen_cache * 2)

2) max_connections * 5

3) operating system limit if positive

4) if operating system limit is Infinity:

open_files_limit value specified at startup, 5000 if none

在配置了open_files_limit的情况下,第三个值的大小会被忽略。
这里还有一个疑问就是为啥ulimit -n显示1024的时候没有起到限制作用呢。我认为的原因是启动mysqld_safe的用户为root,不受这个值的限制。经过测试不管mysqld的启动用户是什么,只要mysqld_safe启动的用户为root,就不受这个限制。只有在mysqld_safe由非root用户启动的时候,才会受到这个限制。

相关链接

MySQL 一个让你怀疑人生的hang死现象

揭秘 MySQL 主从环境中大事务的传奇事迹

MySQL 执行DDL语句 hang住了怎么办?

手把手教你认识OPTIMIZER_TRACE

MySQL行级别并行复制能并行应用多少个binlog group?

binlog server还是不可靠吗?

MySQL binlog基于时间点恢复数据失败是什么鬼?

MySQL高可用工具Orchestrator系列四:拓扑恢复

MySQL高可用工具Orchestrator系列三:探测机制

MySQL高可用工具Orchestrator系列二:复制拓扑的发现

MySQL高可用工具Orchestrator系列一:单节点模式安装

select into outfile问题一则

开源监控系统Prometheus的前世今生

prometheus监控多个MySQL实例

prometheus配置MySQL邮件报警

MySQL问题两则

Kubernetes scheduler学习笔记

执行计划-5:第一个子操作的变化

执行计划-4:谓词的选择时机与使用细节

行计划-3:解释规则

大数据量删除的思考(四)

大数据量删除的思考(三)

日志信息记录表|全方位认识 mysql 系统库

复制信息记录表|全方位认识 mysql 系统库

时区信息记录表|全方位认识 mysql 系统库

优化器成本记录表|全方位认识 mysql 系统库

统计信息记录表|全方位认识 mysql 系统库

Oracle RAC Cache Fusion系列十八:Oracle RAC Statisticsand Wait Events

Oracle RAC Cache Fusion 系列十七:Oracle RAC DRM

Oracle RAC CacheFusion 系列十六:Oracle RAC CurrentBlock Server


更多干货,欢迎来撩~



文章转载自沃趣技术,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论