MySQL Errcode: 24 Too many open files
1 错误详情
MySQL said: Out of resources when opening file '/var/folders/84/b3ghw9z51kg8xlrykdwrvqpw0000gn/T/#sqla0c_e_11f.MAI' (Errcode: 24 "Too many open files")
2 排查问题
可能的原因
- mysql进程打开的文件数量 超过了系统允许的最大数量
排查步骤
-
检查mac 系统文件数量限制
#查看系统句柄配置 命令:
$ launchctl limit
#执行的结果:
zhoujh@zhoujhdeMBP ~ % launchctl limit
cpu unlimited unlimited
filesize unlimited unlimited
data unlimited unlimited
stack 8388608 67104768
core 0 unlimited
rss unlimited unlimited
memlock unlimited unlimited
maxproc 2784 4176
maxfiles 256 unlimited # soft-limit:256 | hard-limit:unlimited
#或者用命令:
$ ulimit -a
#执行的结果:
zhoujh@zhoujhdeMBP ~ % ulimit -a
-t: cpu time (seconds) unlimited
-f: file size (blocks) unlimited
-d: data seg size (kbytes) unlimited
-s: stack size (kbytes) 8192
-c: core file size (blocks) 0
-v: address space (kbytes) unlimited
-l: locked-in-memory size (kbytes) unlimited
-u: processes 2784
-n: file descriptors 256
# 查看当前内核和进程能打开的文件描述符限制
$ sysctl -a | grep files
zhoujh@zhoujhdeMBP ~ % sysctl -a |grep files
kern.maxfiles: 49152 # 系统级的限制
kern.maxfilesperproc: 24576 # 内核级的限
kern.num_files: 6188 -
查看当前mysql进程已用的文件句柄
- lsof使用介绍
- 查看打开文件数量
#利用lsof查看:
lsof -c mysql
#执行结果 可以看出打开了很多文件 说明是文件数超出了256 所以报错
zhoujh@zhoujhdeMBP ~ % lsof -c mysql
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
mysqld 2572 zhoujh cwd DIR 1,7 1152 2319917 /usr/local/var/mysql
mysqld 2572 zhoujh txt REG 1,7 15747544 23743982 /usr/local/Cellar/mariadb@10.3/10.3.23/bin/mysqld
mysqld 2572 zhoujh txt REG 1,7 490556 22873844 /usr/local/Cellar/openssl@1.1/1.1.1g/lib/libssl.1.1.dylib
mysqld 2572 zhoujh txt REG 1,7 2262368 22873850 /usr/local/Cellar/openssl@1.1/1.1.1g/lib/libcrypto.1.1.dylib
mysqld 2572 zhoujh txt REG 1,7 24576 33942989 /usr/local/var/mysql/tc.log
mysqld 2572 zhoujh txt REG 1,7 28512 33930114 /Library/Preferences/Logging/.plist-cache.Ire7fQDK
mysqld 2572 zhoujh txt REG 1,7 1568368 1152921500312826105 /usr/lib/dyld
mysqld 2572 zhoujh 0r CHR 3,2 0t0 310 /dev/null
mysqld 2572 zhoujh 1w REG 1,7 46425 25857787 /usr/local/var/mysql/zhoujhdeMBP.RT-AX88U.err
mysqld 2572 zhoujh 2w REG 1,7 46425 25857787 /usr/local/var/mysql/zhoujhdeMBP.RT-AX88U.err
mysqld 2572 zhoujh 3u REG 1,7 52 2319921 /usr/local/var/mysql/aria_log_control
mysqld 2572 zhoujh 4r DIR 1,7 1152 2319917 /usr/local/var/mysql
mysqld 2572 zhoujh 5u REG 1,7 32768 2320101 /usr/local/var/mysql/aria_log.00000001
mysqld 2572 zhoujh 6u REG 1,7 817889280 2319918 /usr/local/var/mysql/ibdata1
mysqld 2572 zhoujh 7u REG 1,7 0 33942984 /private/var/folders/84/b3ghw9z51kg8xlrykdwrvqpw0000gn/T/ibmCUk7P
mysqld 2572 zhoujh 8u REG 1,7 0 33942985 /private/var/folders/84/b3ghw9z51kg8xlrykdwrvqpw0000gn/T/ibJ9Durq
mysqld 2572 zhoujh 9u REG 1,7 0 33942986 /private/var/folders/84/b3ghw9z51kg8xlrykdwrvqpw0000gn/T/ibrNIlka
mysqld 2572 zhoujh 10u REG 1,7 50331648 2320927 /usr/local/var/mysql/ib_logfile0
mysqld 2572 zhoujh 11u REG 1,7 50331648 2320928 /usr/local/var/mysql/ib_logfile1
mysqld 2572 zhoujh 12u REG 1,7 12582912 33942988 /usr/local/var/mysql/ibtmp1
mysqld 2572 zhoujh 13u REG 1,7 0 33942987 /private/var/folders/84/b3ghw9z51kg8xlrykdwrvqpw0000gn/T/ibBuLfH8
mysqld 2572 zhoujh 14u REG 1,7 180224 2320130 /usr/local/var/mysql/mysql/innodb_table_stats.ibd
mysqld 2572 zhoujh 15u REG 1,7 24576 33942989 /usr/local/var/mysql/tc.log
mysqld 2572 zhoujh 16u REG 1,7 37748736 33908957 /usr/local/var/mysql/sdb/transferto_orders.ibd
mysqld 2572 zhoujh 17u unix 0xaa2db352875e520b 0t0 /tmp/mysql.sock
mysqld 2572 zhoujh 18u REG 1,7 98304 19054104 /usr/local/var/mysql/spin@002dcopy/alarms.ibd
mysqld 2572 zhoujh 19u REG 1,7 2646605824 33908961 /usr/local/var/mysql/sdb/user_account_logs.ibd
mysqld 2572 zhoujh 20u REG 1,7 113246208 33909660 /usr/local/var/mysql/sdb/user_address_details.ibd
mysqld 2572 zhoujh 21u REG 1,7 1908408320 33909679 /usr/local/var/mysql/sdb/user_credits_account_logs.ibd
mysqld 2572 zhoujh 22u systm 0xaa2db352a9d9aafb 0t0 [ctl com.apple.netsrc id 7 unit 41]
mysqld 2572 zhoujh 23u REG 1,7 54525952 33909994 /usr/local/var/mysql/sdb/user_credits_account_reports.ibd
mysqld 2572 zhoujh 24u REG 1,7 310378496 33910006 /usr/local/var/mysql/sdb/user_credits_accounts.ibd
mysqld 2572 zhoujh 25u REG 1,7 98304 33910068 /usr/local/var/mysql/sdb/user_departments.ibd
mysqld 2572 zhoujh 26u REG 1,7 14680064 33910070 /usr/local/var/mysql/sdb/user_discounts.ibd
mysqld 2572 zhoujh 27u REG 1,7 15728640 33910072 /usr/local/var/mysql/sdb/user_favorites.ibd
mysqld 2572 zhoujh 28u REG 1,7 131072 33910075 /usr/local/var/mysql/sdb/user_groups.ibd
mysqld 2572 zhoujh 29u REG 1,7 393216 33910077 /usr/local/var/mysql/sdb/user_pay_limits.ibd
mysqld 2572 zhoujh 30u REG 1,7 98304 33910082 /usr/local/var/mysql/sdb/user_phone_infos.ibd
mysqld 2572 zhoujh 31u REG 1,7 968884224 33910084 /usr/local/var/mysql/sdb/user_point_logs.ibd
mysqld 2572 zhoujh 32u REG 1,7 1493172224 33910307 /usr/local/var/mysql/sdb/user_verifications.ibd
mysqld 2572 zhoujh 33u REG 1,7 2113929216 33910684 /usr/local/var/mysql/sdb/users.ibd
mysqld 2572 zhoujh 34u REG 1,7 114688 33911079 /usr/local/var/mysql/sdb/voucher_items.ibd -
可以看出mysql打开的文件句柄数量很多,应该是超出了最大256的限制 所以报错
3 解决办法
1 通过launchctl修复
# Usage: launchctl limit \[<limit-name> \[<both-limits> | <soft-limit> <hard-limit>\]
# 查看文件描述符限制
launchctl limit maxfiles
maxfiles 256 unlimited
# 修改软限制为512 系统重启失效
sudo launchctl limit maxfiles 512 unlimited
# 可将launchctl子命令写入/etc/launchd.conf中
# 在launchd启动时 会执行该文件中的命令
limit maxfiles 512 unlimited
2 通过添加plist文件修复(推荐)
-
新建文件 Library/LaunchDaemons/limit.maxfiles.plist 文件,写入
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN"
"http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>Label</key>
<string>limit.maxfiles</string>
<key>ProgramArguments</key>
<array>
<string>launchctl</string>
<string>limit</string>
<string>maxfiles</string>
<string>64000</string>
<string>524288</string>
</array>
<key>RunAtLoad</key>
<true/>
<key>ServiceIPC</key>
<false/>
</dict>
</plist> -
修改文件权限
sudo chown root:wheel /Library/LaunchDaemons/limit.maxfiles.plist
sudo chmod 644 /Library/LaunchDaemons/limit.maxfiles.plist -
加载 plist 文件
(或重启系统后生效 launchd 在启动时会自动加载该目录的 plist)
sudo launchctl load -w /Library/LaunchDaemons/limit.maxfiles.plist
-
确认更改后的限制
launchctl limit maxfiles
4 参考1
在 Mac OS X 下,有如下三个命令与系统资源有关。
launchctl
-
介绍
launchctl 管理 OS X 的启动脚本,控制启动计算机时需要开启的服务 (通过后台进程 launchd)。也可以设置定时执行特定任务的脚本,类似 Linux cron。
例如,开机时自动启动 Apache 服务器:
$ sudo launchctl load -w /System/Library/LaunchDaemons/org.apache.httpd.plist
关于 launchctl 的 plist 格式和用法参考:
简单来说,plist 文件用类似 XML 格式定义了一个命令 (及启动参数) 和该命令的执行方式(定时执行,系统启动执行,用户登录执行等)。我们这里不着重讨论,我们关心 launchctl 中如何查看 / 更改系统资源限制。
-
launchctl 查看|更改系统资源限制
# Usage: launchctl limit \[<limit-name> \[<both-limits> | <soft-limit> <hard-limit>\]
# 查看文件描述符限制
launchctl limit maxfiles
maxfiles 256 unlimited
# 修改软限制为512 系统重启失效
sudo launchctl limit maxfiles 512 unlimited
# 可将launchctl子命令写入/etc/launchd.conf中
# 在launchd启动时 会执行该文件中的命令
limit maxfiles 512 unlimited
-
通过写入plist文件 更改系统资源限制
通过将更改命令写入 plist 文件,并在启动时执行,也可永久更改资源限制:
-
新建文件 Library/LaunchDaemons/limit.maxfiles.plist 文件,写入
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN"
"http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>Label</key>
<string>limit.maxfiles</string>
<key>ProgramArguments</key>
<array>
<string>launchctl</string>
<string>limit</string>
<string>maxfiles</string>
<string>64000</string>
<string>524288</string>
</array>
<key>RunAtLoad</key>
<true/>
<key>ServiceIPC</key>
<false/>
</dict>
</plist> -
修改文件权限
sudo chown root:wheel /Library/LaunchDaemons/limit.maxfiles.plist
sudo chmod 644 /Library/LaunchDaemons/limit.maxfiles.plist -
加载 plist 文件
(或重启系统后生效 launchd 在启动时会自动加载该目录的 plist)
sudo launchctl load -w /Library/LaunchDaemons/limit.maxfiles.plist
-
确认更改后的限制
launchctl limit maxfiles
sysctl
大多数类 Unix 系统都通过 (Linux/*BSD/OS X) 都提供该命令来更改资源限制和内核配置:
# 查看当前内核和进程能打开的文件描述符限制
$ sysctl -A | grep kern.maxfiles
kern.maxfiles: 12288 # 系统级的限制
kern.maxfilesperproc: 10240 # 内核级的限制
# 通过sysctl命令热更改 系统重启后失效
$ sysctl -w kern.maxfilesperproc=20480
# 通过配置文件永久更改 重启生效
# 在/etc/sysctl.conf中写入
kern.maxfiles=20480 kern.maxfilesperproc=24576
ulimit
ulimit 是 shell 的内置命令,用于查看 / 更改当前 shell 及其创建的子进程的资源限制。使用比较简单:
\# 查看当前shell(及其子进程)的所有限制
ulimit -a
# 改变进程能打开的最大文件描述符数软限制 当shell关闭后失效
# 将其写入对应shell的startup文件(如~/.bashrc, ~/.zshrc),可保留更改
ulimit -S -n 1024
区别联系
这三个命令的关系在 Mac OS X 各版本中尤其混乱,先说说本人的一些试验 (Mac OS X 10.10.3):
-
在默认配置下 (不配置 plist 和 sysctl.conf),launchctl 的 maxfiles 默认值为 (256, unlimited),sysctl 的 maxfiles 默认值为 (12288, 10240),而 ulimit -n 得到的值为 4864。
-
当不定义 plist 而定义 sysctl.conf,那么重启后 launchctl 和 ulimit 看到的上限仍为默认值,sysctl 看到的上限与 sysctl.conf 定义的一致。
-
当同时在
/etc/sysctl.conf
和/Library/LaunchDaemons/limit.maxfiles.plist
中定义 maxfiles 时,plist 文件中的配置会覆盖 sysctl.conf 中的配置。如果通过系统重启应用 plist,三个命令看到的上限均为 plist 配置。如果通过 launchctl load 加载 plist,则会同步影响 sysctl 看到的上限,而不会影响 shell 下的 ulimit 上限。 -
如果通过 launchctl 配置的软上限和硬上限分别为 S 和 H(非 unlimited),那么通过 launchctl 应用配置后最终得到软上限和硬上限都为 S。如果设定的上限为 S 和 unlimited,实际上应用的参数为 S 和 10240(sysctl 中 kern.maxfilesperproc 默认值),当 S > 10240 时,会设置失败,S < 10240 时,会得到 (S, 10240)
-
ulimit -H -n 1000
降低硬上限无需 Root 权限,升高则需要
趁着头大,还可以看看这几篇文章:
- open files limit does not work as before in osx yosemite
- maximum files in mac os x
- how to persist ulimit settings in osx mavericks
- open files limit in max os x
- increase the maximum number of open file descriptors in snow leopard
网上对 Mac OS X 各版本的解决方案各不相同,并且对这三个命令 (特别是 launchctl 和 sysctl) 在资源限制上的联系与区别也没有清晰的解释。
按照我的理解和折腾出来的经验:
- ulimit 只影响当前 Shell 下的进程,并且受限于 kern.maxfilesperproc
- 如果配置了 plist,那么重启后,ulimit 和 sysctl 均会继承 plist 中的值
- 热修改 sysctl 上限值不会影响 launchctl,而反之,launchctl 会影响 sysctl 上限值
综上,在 Mac OS X 10.10(我的版本,没试过之前的) 之后,使用 plist 是最合理的方案 (但 launchctl 貌似只能设定一样的软限制和硬限制,如果将硬限制设为 ulimited,则会使用 kern.maxfilesperproc 值)。在系统重启后,kern.maxfilesperproc 和 ulimit -n 都会继承 plist maxfiles 的值。
5 参考2
launchctl 参考
launchctl 管理 MacOS 的启动脚本,控制启动计算机时需要开启的服务。也可以设置定时执行特定任务的脚本,就像Linux cron一样。
常用命令
# 1.显示当前的启动脚本
launchctl list
# 2.开机时自动启动Apache服务器
sudo launchctl load -w /System/Library/LaunchDaemons/org.apache.httpd.plist
# 3.设置开机启动并立即启动改服务
launchctl load -w **.pist
# 4. 设置开机启动但不立即启动服务
launchctl load **.pist
# 5. 停止正在运行的启动脚本
sudo launchctl unload [path/to/script]
# 6. 再加上-w选项即可去除开机启动
sudo launchctl unload -w [path/to/script]
执行定时脚本|设置开机启动步骤
# 1.写执行脚本 (通过 brew 安装软件 brew 会为我们自动生成。)
# 2. 去对应的目录下建立plist文件
# 3. 加载服务
# 3.1 cd 进入指定 plist 文件目录
# 3.2 加载和取消加载
# 加载
launchctl load *.plist
# 取消 加载
launchctl unload *.plist
#3.3 查看服务
launchctl list
ulimit | sysctl | lauchctl 区别
三者介绍
-
ulimit
- This is a builtin command of your shell (bash/ash/zsh etc). It temporarily sets process limits for the current shell. This is not OS X specific by the way.
- 这是一种嵌入shell的命令,只能临时设置当前shell(也就是当前进程)的参数。unix-like OS都有。
-
sysctl
- Most unix-like (Linux/*BSD/OS X) systems set global limit/kernel settings via the
sysctl
command//etc/sysctl.conf
config file. But see below for the OS X caveat. - 大部分unix-like OS都采用这个来设置全局的内核限制,sysctl为命令,/etc/sysctl.conf为配置文件。不过请看下面的launchctl
- Most unix-like (Linux/*BSD/OS X) systems set global limit/kernel settings via the
-
launchctl
- Seems like OS X does not honor
sysctl.conf
on startup anymore ( https://discussions.apple.com/thread/2781309?start=0&tstart=0). So on OS X, it looks likesysctl
is merely usable for temporarily setting the global limits. - 看起来OS X在启动的时候不在尊重sysctl.conf的配置(附链接)。所以在OS X上,sysctl仅仅能够临时设置全局限制。
- Seems like OS X does not honor
说明
ulimit
- ulimit
- ulimit仅作用于当前shell,也就是当前进程
- ulimit -n 的设置理所当然的也是临时设置
- ulimit下的open files才是真正影响当前进程打开文件的配置
- 修改open files的上限不能超过 kern.maxfilesperproc设置(参见下面sysctl参数)
- launchctl
- launchctl为macOS特有配置
- $ launchctl limit maxfiles
- maxfiles 1024 10240
- 可将launchctl子命令写入/etc/launchd.conf中
- 有软配和硬配。软配为每个进程可自由控制,但不能超过硬配;硬配为只有root才能修改,目的就是给软配划定上限。
- 修改该项配置会直接同时设置sysctl的 kern.maxfilesperproc参数
- 热修改sysctl上限值不会影响launchctl,而反之,launchctl会影响sysctl上限值
- sysctl
- sysctl为系统控制
- $ sysctl -a|grep files
- kern.maxfiles: 10240
- kern.maxfilesperproc: 512
- 由以上两个配置项决定,第一个为内核总文件上限,第二个为每个进程允许的上限
系统的资源是有限的 (如 CPU,内存,内核所能打开的最大文件数等),资源限制对针对进程能使用的系统资源设定上限。防止恶意进程无限制地占用系统资源。
资源限制分为两种,硬限制 (Hard Limit) 和软限制(Soft Limit),软限制作用于实际进程并且可以修改,但不能超过硬限制,硬限制只有 Root 权限才能修改。