网站建设

破除MySQL打开的文件描述符限制-数据库Too many open files问题

由于挖站否免费CN2空间用户增多,近期总是出现半夜Mysql进程挂掉的情况,查询了一下Mysql的错误日志,提示有:[ERROR] Error in accept: Too many open files,原来是因为open files不足导致数据库挂掉了,尤其是晚上DirectAdmin系统备份时更是如此。

登录 shell 的 ulimit 和数据库服务进程的限制可能不同。先看正在运行的 mysqld 的软、硬上限,再对照 MySQL 的 open_files_limit,两者都没有固定为 1024。

这篇文章就是来分享一下如何解决错误:[ERROR] Error in accept: Too many open files的问题,更多的关于服务器优化以及问题解决方法,参考:

  1. 让图片飞一会儿!网站图片WebP格式批量转换设置及加速效果体验
  2. 巧用又拍云FTP和坚果云WebDAV-打造个人文件备份和数据云存储
  3. VPS主机和服务器安全防护:SSH修改端口,添加白名单,仅限密钥登录

PS:2026年11月5日更新,纠正了 shell 与数据库进程的文件上限关系,补上 systemd 持久化配置和实际生效值的核验。

一、数据库问题详情

查看数据库错误日志,如果用的是DirectAdmin面板,相关的日志路径如下:

#DirectAdmin:
/var/log/directadmin/error.log
/var/log/directadmin/errortaskq.log
/var/log/directadmin/system.log
/var/log/directadmin/security.log


#Apache:
/var/log/httpd/error_log
/var/log/httpd/access_log
/var/log/httpd/suexec_log
/var/log/httpd/fpexec_log
/var/log/httpd/domains/domain.com.error.log
/var/log/httpd/domains/domain.com.log
/var/log/messages (generic errors)


#Proftpd:
/var/log/proftpd/access.log
/var/log/proftpd/auth.log
/var/log/messages (generic errors)


#PureFTPd:
/var/log/pureftpd.log


#Dovecot and vm-pop3d:
/var/log/maillog
/var/log/messages


#named (bind):
/var/log/messages


#exim:
/var/log/exim/mainlog
/var/log/exim/paniclog
/var/log/exim/processlog
/var/log/exim/rejectlog

#(on FreeBSD, they have "exim_" in front of the filenames)

#mysqld:
#RedHat:
/var/lib/mysql/server.hostname.com.err

#FreeBSD and Debian:
/usr/local/mysql/data/server.hostname.com.err


#crond:
/var/log/cron


#To view a log file, run:
less /var/log/filename

#Where /var/log/filename is the path of the log you wish to view.  If the log is too large you can use the "tail" command:
tail -n 30 /var/log/filename

#Where 30 is the number of lines from the end you wish to view.

打开Mysql错误日志,一般会提示如下错误:

190902  3:16:52 [ERROR] Error in accept: Too many open files
190902  3:21:08 [ERROR] Error in accept: Too many open files
190902  3:25:24 [ERROR] Error in accept: Too many open files
190902  3:29:40 [ERROR] Error in accept: Too many open files
190902  3:33:56 [ERROR] Error in accept: Too many open files
190902  3:38:12 [ERROR] Error in accept: Too many open files
190902  3:42:28 [ERROR] Error in accept: Too many open files
190902  3:46:44 [ERROR] Error in accept: Too many open files
190902  3:51:00 [ERROR] Error in accept: Too many open files
190902  3:55:16 [ERROR] Error in accept: Too many open files
190902  3:59:32 [ERROR] Error in accept: Too many open files
190902  4:03:48 [ERROR] Error in accept: Too many open files
190902  4:08:04 [ERROR] Error in accept: Too many open files
190902  4:12:20 [ERROR] Error in accept: Too many open files
190902  4:16:37 [ERROR] Error in accept: Too many open files
190902  4:20:53 [ERROR] Error in accept: Too many open files
190902  4:25:09 [ERROR] Error in accept: Too many open files
190902  4:29:25 [ERROR] Error in accept: Too many open files
190902  4:33:41 [ERROR] Error in accept: Too many open files
190902  4:37:57 [ERROR] Error in accept: Too many open files
190902  4:42:13 [ERROR] Error in accept: Too many open files
190902  4:46:29 [ERROR] Error in accept: Too many open files
190902  4:50:45 [ERROR] Error in accept: Too many open files

二、数据库问题分析

2.1 查看限制

ulimit -a 显示当前 shell 的限制。用 systemd 启动数据库时,还要看数据库服务本身。

[root@sc3 ~]# ulimit -a
core file size          (blocks, -c) 0
data seg size           (kbytes, -d) unlimited
scheduling priority             (-e) 0
file size               (blocks, -f) unlimited
pending signals                 (-i) 15675
max locked memory       (kbytes, -l) 64
max memory size         (kbytes, -m) unlimited
open files                      (-n) 1024
pipe size            (512 bytes, -p) 8
POSIX message queues     (bytes, -q) 819200
real-time priority              (-r) 0
stack size              (kbytes, -s) 8192
cpu time               (seconds, -t) unlimited
max user processes              (-u) 15675
virtual memory          (kbytes, -v) unlimited
file locks                      (-x) unlimited

以下以 mysql.service 为例,有些发行版叫 mysqld.service 或 mariadb.service。按实际服务名检查 systemd 配置值和运行进程的上限:

#直接查看 open files限制数字
ulimit -n

#仅查看soft 和 hard open files limits :
ulimit -Hn
ulimit -Sn

# 下面换成实际服务名
systemctl show mysql.service -p MainPID -p LimitNOFILE -p LimitNOFILESoft
pid=$(systemctl show mysql.service -p MainPID --value)
[ "$pid" -gt 0 ] && grep -F "Max open files" "/proc/$pid/limits"

2.2 修改limits.conf

方法一:

以下是旧式登录会话和 SysV 启动脚本的记录。limits.conf 一般由 PAM 会话应用,systemd 直接启动服务时用第三节的服务覆盖配置。

#To set the ceiling of the limits available (the max a soft or hard limit can be set by each user).
#NOTE: this is set by a PAM during authentication, and NOT at boot. 
#编辑文件

vi /etc/security/limits.conf

#Add the following to bottom of file to set for everything *:
#添加以下谷贱伤农

* soft nofile 1024000
* hard nofile 1024000
* soft nproc 10240
* hard nproc 10240

#To set only a specific user, like mysql then put in:
#或者指定Mysql

mysql hard nofile 1024000
mysql soft nofile 1024000

#Repeat for /etc/security/limits.d/90-nproc.conf
#同样对90-nproc.conf也是一样的操作

vi /etc/security/limits.d/90-nproc.conf

#Add the following:

* soft nofile 1024000
* hard nofile 1024000
* soft nproc 10240
* hard nproc 10240

#root soft nproc unlimited
#I selected '1024000', which is fairly high; you can surely set this lower to something like '102400',请根据自己的实际情况来设定数字

旧环境也曾在 init 脚本中设置限制。下面的数字和路径仅用于对照旧系统;现有系统先确认实际启动方式。

ulimit -Hn 1024000


#Edit /etc/init.d/mysqld and add this to the top, after #!/bin/sh
#或者编辑修改/etc/init.d/mysqld,加入以下代码:
ulimit -HSn 1024
ulimit -HSn 32768
ulimit -HSn 1024000

方法二:

只给数据库调整限制时,应修改数据库服务自己的配置。给所有用户设同一个很大的文件上限,会扩大变更范围,也不能保证 systemd 服务会采用该值。

2.3 修改my.cnf文件

如目标版本和启动方式需要,可在实际加载的 [mysqld] 配置中设定 open_files_limit。它是启动时变量,系统服务上限仍然有效。下面的值是示例,按报错及文件使用量估算。

[mysqld]
open_files_limit = 32768

安排维护窗口重启对应数据库服务。以下是旧环境的命令,systemd 环境见第三节。

/etc/init.d/mysqld restart
#或者
service mysqld restart

2.4 查看是否生效

执行以下命令:

mysql -u root -p 
show global variables like 'open%';
#如果是DirectAdmin面板
mysql -u da_admin -p 
show global variables like 'open%';

可以查看到open_files_limit已经修改成功了:

三、重启后失效问题

systemd 环境用 systemctl edit 建立服务 drop-in,让配置在重启后继续生效。服务名和数值按实际情况换。下面先打开编辑器,把 [Service] 两行保存到 drop-in,然后再执行后面的命令。

sudo systemctl edit mysql.service
# 在编辑器中保存:
[Service]
LimitNOFILE=32768

# 在维护窗口,回到终端再执行:
sudo systemctl daemon-reload
sudo systemctl restart mysql.service

四、总结

重启后核对运行进程的 /proc/<PID>/limits 和 SQL 查询的 open_files_limit,同时看数据库日志是否还有上限警告。设置值与最终生效值可能不同。官方说明:https://dev.mysql.com/doc/refman/8.4/en/server-system-variables.html#sysvar_open_files_limit 。

当然,如果你不想修改系统设置,也可以使用root帐号,运行mysqld_safe脚本启动MySQL(或者使用mysql.server启动),加上命令:–open-files-limit是可以成功设置的,因为mysqld_safe启动MySQL时,其实是在启动mysqld程序之前,调用了ulimit -n $open_files来实现文件描述符的限制。

./mysqld_safe --open-files-limit=25000 &
root@(none) 02:50:54>show variables like "%open_files_limit%";
+------------------+-------+
| Variable_name    | Value |
+------------------+-------+
| open_files_limit | 25000 |
+------------------+-------+

文章出自:挖站否 https://wzfou.com/mysql-too-files/,版权所有。本站文章除注明出处外,皆为作者原创文章,可自由引用,但请注明来源。部分内容参考自:orczhou(http://www.orczhou.com/index.php/2010/10/mysql-open-file-limit/)、duntuk(http://duntuk.com/how-raise-ulimit-open-files-and-mysql-openfileslimit)。

文章更新于: 2026年11月5日 上午12:35

Qi

关于站长(Qi),2008年开始混迹于免费资源圈中,有幸结识了不少的草根站长。之后自己摸爬滚打潜心学习Web服务器、VPS、域名等,兴趣广泛,杂而不精,但愿将自己经验与心得分享出来与大家共勉。

查看评论