欢送来到 GreatSQL社区分享的MySQL技术文章,如有疑难或想学习的内容,能够在下方评论区留言,看到后会进行解答

lsof中附加不同参数产生的后果也不同,小心“踩坑”。

1、背景:

偶尔发现数据库连不上,在数据库的err日志中,呈现了“Too many open files”谬误,都晓得这个是mysqld过程触发了句柄限度,导致无奈建设新连贯。

度娘下面找到了统计句柄数的命令

lsof -n|awk '{print $2}'|sort|uniq -c|sort -nr| head -n 10

发现输入的后果远超了ulimit -n的后果。然而报错景象才继续不长时间,失常状况下不可能产生这么多句柄。

为了钻研这个问题的根因,在本人的服务器下面模仿了以下测试。

服务器配置4C8G,MySQL 8.0.22,lsof版本为4.87(为什么特地介绍lsof版本,后续会提到,很重要)

2、测试过程:

1、在服务器下面装置好MySQL,设置上面的参数,重启数据库服务

max_connections=150open_files_limit=1000

此时,数据库过程的open_files_limit为2160

mysql> show variables like '%open%';+----------------------------+-------+| Variable_name              | Value |+----------------------------+-------+| have_openssl               | YES   || innodb_open_files          | 1000  || mysqlx_port_open_timeout   | 0     || open_files_limit           | 2160  || table_open_cache           | 1000  || table_open_cache_instances | 16    |+----------------------------+-------+6 rows in set (0.01 sec)

其计算公式为table_open_cache*2+max_connections+10 具体见上面的官网介绍

2、此时数据库刚刚启动,查看过程占用的句柄数

[root@greatdb mysql]# ps -ef| grep mysqlroot      6239  8644  0 16:25 pts/5    00:00:00 mysql -urootroot     10134  8260  0 16:42 pts/1    00:00:00 mysql -urootroot     10177     1  0 16:47 ?        00:00:00 /bin/sh /usr/local/mysql/bin/mysqld_safe --defaults-file=/data/mysql/my.cnfmysql    11604 10177  8 16:47 ?        00:00:02 /usr/local/mysql/bin/mysqld --defaults-file=/data/mysql/my.cnf --basedir=/usr/local/mysql --datadir=/data/mysql/data --plugin-dir=/usr/local/mysql/lib/plugin --user=mysql --log-error=/data/mysql/logs/mysqld-error.log --open-files-limit=1000 --pid-file=/data/mysql/mysqld.pid --socket=/data/mysql/mysql.sock --port=3306root     11696  8572  0 16:47 pts/2    00:00:00 grep --color=auto mysql[root@greatdb mysql]# [root@greatdb mysql]# [root@greatdb mysql]# lsof -n|awk '{print $2}'|sort|uniq -c|sort -nr| head -n 10   5727 11604   1575 1384    525 1550    455 879    371 561    135 1101    130 1001    120 16780    114 1304     88 16894[root@greatdb mysql]#

能够看到刚刚启动的数据库,用下面的命令统计进去的句柄数5727就曾经超过了设置的值2160了,然而数据库依然能够失常应用和连贯。

2、此时进入数据库,批改最大连贯限度,用于模仿实在超过句柄的状况

set global max_connections=10000

3、在数据库中创立三个分区表,用于疾速占用文件句柄数

create database test;create table test.tb1(id int, c varchar(10)) partition by hash(id) partitions 1024;create table test.tb2(id int, c varchar(10)) partition by hash(id) partitions 1024;create table test.tb3(id int, c varchar(10)) partition by hash(id) partitions 1024;

4、此时再次应用下面的命令查问句柄数

[root@greatdb mysql]# lsof -n|awk '{print $2}'|sort|uniq -c|sort -nr| head -n 10  73485 11604   1575 1384    525 1550    455 879    371 561    135 1101    130 1001    120 16780    114 1304     88 16894[root@greatdb mysql]#

5、能够看到mysql的过程“占用”句柄数曾经达到73485,远远超过了理论容许的值了,开始狐疑这个统计值不对。

6、应用另外的命令 lsof -p 11604 |wc -l; ls /proc/11604/fd |wc -l 来统计句柄和关上文件,发现比拟失常,在正当范畴内

[root@greatdb mysql]# lsof -p 11604 |wc -l;  ls /proc/11604/fd |wc -l10661021[root@greatdb mysql]#

7、最终比照lsof -n | head 和lsof -p 11604 |head 发现了差别,lsof -n 的后果多了一列TID,察看后发现是线程编号,其值和performance_schema.threads中的thread_id可能对应上

[root@greatdb mysql]# lsof -p 11604 | headCOMMAND   PID  USER   FD      TYPE             DEVICE   SIZE/OFF    NODE NAMEmysqld  11604 mysql  cwd       DIR              253,1       4096 1310723 /data/mysql/datamysqld  11604 mysql  rtd       DIR              253,1       4096       2 /mysqld  11604 mysql  txt       REG              253,1  441771255  927033 /usr/local/mysql/bin/mysqldmysqld  11604 mysql  DEL       REG               0,11            6526074 /[aio]mysqld  11604 mysql  DEL       REG               0,11            6526073 /[aio]mysqld  11604 mysql  DEL       REG               0,11            6526072 /[aio]mysqld  11604 mysql  DEL       REG               0,11            6526071 /[aio]mysqld  11604 mysql  DEL       REG               0,11            6526070 /[aio]mysqld  11604 mysql  DEL       REG               0,11            6526069 /[aio][root@greatdb mysql]# [root@greatdb mysql]# [root@greatdb mysql]# lsof -n | head COMMAND     PID   TID    USER   FD      TYPE             DEVICE   SIZE/OFF       NODE NAMEsystemd       1          root  cwd       DIR              253,1       4096          2 /systemd       1          root  rtd       DIR              253,1       4096          2 /systemd       1          root  txt       REG              253,1    1632744     136135 /usr/lib/systemd/systemdsystemd       1          root  mem       REG              253,1      20064     132877 /usr/lib64/libuuid.so.1.3.0systemd       1          root  mem       REG              253,1     265576     134383 /usr/lib64/libblkid.so.1.1.0systemd       1          root  mem       REG              253,1      90176     132861 /usr/lib64/libz.so.1.2.7systemd       1          root  mem       REG              253,1     157424     132876 /usr/lib64/liblzma.so.5.2.2systemd       1          root  mem       REG              253,1      23968     133092 /usr/lib64/libcap-ng.so.0.0.0systemd       1          root  mem       REG              253,1      19896     133076 /usr/lib64/libattr.so.1.1.0

8、通过多方征询及材料查阅,理解到在lsof 4.82版本后,默认会统计出每个线程的句柄,即默认加上了-K参数,这样实现后,以前的命令 lsof -n|awk '{print $2}'|sort|uniq -c|sort -nr| head -n 10 统计进去的数据就约等于理论句柄数 * 线程数,也就是咱们后面看到的后果,统计数据数字很大。

9、新lsof版本统计句柄正确的语法是 lsof -n -Ki|awk '{print $2}'|sort|uniq -c|sort -nr| head -n 10,统计进去后数据失常

[root@greatdb mysql]# lsof -Ki -n| awk '{print $2}' | sort | uniq -c | sort -nr | head   1065 11604    130 1001     91 879     84 8643     84 8641     84 8622     84 8603     84 8570     84 8258     84 8156

10、应用循环的形式,批量创立数据库会话连贯,发现句柄到设置极限后,还会超45个句柄数,在此之后手动创立连贯,会始终期待,mysql-err日志中呈现谬误“Too many open files”

for x in {1..1139}; do nohup mysql -uroot -e 'select sleep(240)' & done

11、在无奈建设新连贯的状况下,查问过程占用句柄数

[root@greatdb mysql]# lsof -p 11604 |wc -l2205

12、至此找到正确统计过程句柄的办法,计算MySQL句柄下限计算形式,并且精确复现异样场景。

3、总结:

  • lsof 统计句柄数据,与版本有很大关系,如果是4.82之后的版本,统计过程句柄数,须要加上参数-Ki
  • MySQL启动时占用句柄数84,当table_open_cache设置为1000时,除开连贯句柄,最多占用句柄1065个,次要蕴含共享库so、ibd文件、日志文件、临时文件等,每个链接再独自占用一个句柄
  • MySQL过程的最大句柄数,是参数open_files_limit + 45,这个是测试进去的,并没有找到具体代码出处
  • MySQL的句柄限度,是由参数max_connections、table_open_cache独特影响的,并且不受操作系统限度(测试了操作系统ulimit -n 1024的状况下,MySQL 的open_files_limit仍然能够为2160)
  • 文件句柄在线程间是共享的,因而关上一个ibd文件,不管有多少session拜访,都只会占用一个句柄

参考文章

https://github.com/rapidoid/r...

https://github.com/draios/sys...

https://dev.mysql.com/doc/ref...

Enjoy GreatSQL :)

文章举荐:

技术分享 | MGR最佳实际(MGR Best Practice)
https://mp.weixin.qq.com/s/66...

技术分享 | 万里数据库MGR Bug修复之路
https://mp.weixin.qq.com/s/Ia...

Macos零碎编译percona及局部函数在Macos零碎上运算差别
https://mp.weixin.qq.com/s/jA...

技术分享 | 利用systemd治理MySQL单机多实例
https://mp.weixin.qq.com/s/iJ...

产品 | GreatSQL,打造更好的MGR生态
https://mp.weixin.qq.com/s/By...

产品 | GreatSQL MGR优化参考
https://mp.weixin.qq.com/s/5m...

对于 GreatSQL

GreatSQL是由万里数据库保护的MySQL分支,专一于晋升MGR可靠性及性能,反对InnoDB并行查问个性,是实用于金融级利用的MySQL分支版本。

Gitee:
https://gitee.com/GreatSQL/Gr...

GitHub:
https://github.com/GreatSQL/G...

微信&QQ群:

可扫码增加GreatSQL社区助手微信好友,发送验证信息“加群”退出GreatSQL/MGR交换微信群,亦可间接扫码退出GreatSQL/MGR交换QQ群。

本文由博客一文多发平台 OpenWrite 公布!