MySQL 报错 “Can't create a new thread; if you are not out of available memory, you can consult the manual for a possible OS-dependent bug (error.:11/35)” 分析及解决方案
该报错是 MySQL 线程资源耗尽类核心错误,核心含义是:MySQL 尝试创建新线程(处理客户端连接 / 查询)时失败,失败原因要么是服务器内存不足,要么是操作系统的线程 / 进程限制触发,error:11/35 是系统级资源不足的错误码(11=EAGAIN / 资源临时不足,35=ENOSPC / 线程数达到上限)。以下从报错本质、核心原因、排查步骤、解决方案、预防措施五方面系统说明。
一、报错本质与关键背景
1. 核心逻辑
MySQL 采用 “一个连接对应一个线程” 的模型(默认),每接收一个客户端连接、执行一个查询,都会创建新的线程。当满足以下任一条件时,线程创建失败并触发该报错:
- 内存耗尽:服务器物理内存 / 交换分区不足,无法为新线程分配栈内存;
- 系统线程限制:操作系统对进程 / 用户的最大线程数、文件描述符限制触发;
- MySQL 自身限制:
max_connections等参数设置过小,或线程缓存(thread_cache_size)未生效; - 系统级 Bug:极少数情况是 OS 内核 / MySQL 版本兼容问题导致线程创建异常。
2. 错误码含义
| 错误码 | 系统含义 | 触发场景 |
|---|---|---|
| 11 | EAGAIN(Resource temporarily unavailable) | 内存不足、线程数临时超出系统阈值,重试可能成功 |
| 35 | ENOSPC(No space left on device) | 线程数达到操作系统硬限制,或线程栈内存耗尽,无法创建新线程 |
二、核心报错原因分析
| 原因分类 | 具体说明 |
|---|---|
| 服务器内存不足 | 物理内存被 MySQL 连接线程、其他进程占满,新线程分配栈内存(默认 1MB / 线程)失败 |
| 操作系统线程限制 | Linux 系统对 mysql 用户 / 进程的最大线程数(pthread)、最大进程数(nproc)限制 |
| MySQL 连接参数不合理 | max_connections 设值过高(超出内存承载)或过低(业务连接数达上限);thread_cache_size 过小,线程复用率低 |
| 系统文件描述符不足 | Linux 对进程 / 用户的最大文件描述符(nofile)限制,线程创建依赖文件描述符 |
| 交换分区(swap)不足 | 物理内存耗尽后,swap 分区也满,无法临时分配内存 |
| 版本 / 内核兼容问题 | MySQL 版本与 OS 内核不兼容(如老旧 MySQL 运行在新内核),触发线程创建 Bug |
三、快速排查步骤(按优先级)
步骤 1:检查 MySQL 连接 / 线程状态
sql
-- 1. 查看 MySQL 核心线程/连接参数
SHOW VARIABLES LIKE '%connection%';
SHOW VARIABLES LIKE '%thread%';
-- 重点关注:
-- max_connections:MySQL 允许的最大连接数(默认 151)
-- thread_cache_size:线程缓存大小(默认 8)
-- thread_stack:每个线程的栈内存(默认 1024K)
-- 2. 查看当前连接/线程使用情况
SHOW STATUS LIKE 'Threads_%';
-- 关键指标:
-- Threads_connected:当前已建立的连接数
-- Threads_running:当前活跃线程数(执行查询的线程)
-- Threads_created:累计创建的线程数(数值过大说明线程复用率低)
-- 3. 查看是否达到最大连接数
SHOW STATUS LIKE 'Max_used_connections';
-- 若 Max_used_connections ≥ max_connections,说明连接数达上限
步骤 2:检查服务器内存 /swap 使用情况
bash
运行
# 1. 查看内存/swap 整体使用(free -h 易读格式)
free -h
# 关键输出:
# total used free shared buff/cache available
# Mem: 15Gi 14Gi 100Mi 128Mi 800Mi 200Mi
# Swap: 2Gi 2Gi 0Mi # swap 耗尽,内存不足
# 2. 查看 MySQL 进程内存占用
top -p $(pgrep mysqld)
# 看 %MEM 列,若接近 100% 说明 MySQL 占满内存
# 3. 查看系统整体内存占用(定位内存大户)
top
# 按 M 排序,看其他进程是否占用大量内存
步骤 3:检查 Linux 系统资源限制
# 1. 查看当前 mysql 用户的资源限制
su - mysql -c "ulimit -a"
# 重点关注:
# max user processes (-u):最大进程/线程数(默认 1024)
# open files (-n):最大文件描述符(默认 1024)
# 2. 查看系统级线程限制(Linux)
cat /proc/sys/kernel/threads-max # 系统总线程数上限
cat /proc/sys/vm/max_map_count # 内存映射限制(影响线程创建)
# 3. 查看 mysqld 进程的资源限制
cat /proc/$(pgrep mysqld)/limits
# 重点看 Max processes、Max open files
步骤 4:检查交换分区使
# 1. 查看 swap 分区状态
swapon --show
# 2. 若 swap 未开启/不足,执行:
swapon /dev/sda2 # 临时开启 swap 分区
步骤 5:检查系统日志(排查内核 / Bug 问题)
# 查看系统内核日志(是否有线程创建失败、OOM 记录)
dmesg | grep -i mysql | grep -i thread
dmesg | grep -i oom # 查看是否有 OOM 杀进程记录
# 查看 MySQL 错误日志
SHOW VARIABLES LIKE 'log_error';
grep -i "create a new thread" /var/log/mysqld.log
四、针对性解决方案
方案 1:紧急释放内存(恢复业务)
场景 1.1:内存 /swap 耗尽 → 释放内存
# 1. 终止非核心进程(释放内存)
kill -9 占用内存的非核心进程ID
# 2. 清理系统缓存(临时释放 buff/cache)
sync && echo 3 > /proc/sys/vm/drop_caches
# 3. 临时扩容 swap 分区(若 swap 不足)
# 创建 4G 临时 swap 文件
fallocate -l 4G /swapfile
chmod 600 /swapfile
mkswap /swapfile
swapon /swapfile
场景 1.2:连接数达上限 → 临时增大 max_connections
-- 临时增大最大连接数(需 SUPER 权限,重启失效)
SET GLOBAL max_connections = 500;
-- 临时增大线程缓存,提高复用率
SET GLOBAL thread_cache_size = 64;
方案 2:调整 Linux 系统资源限制(核心解决线程 / 文件描述符限制)
步骤 1:修改用户级限制(/etc/security/limits.conf)
vi /etc/security/limits.conf
# 添加以下内容(针对 mysql 用户)
mysql soft nproc 65535 # 软限制:最大进程/线程数
mysql hard nproc 65535 # 硬限制
mysql soft nofile 65535 # 软限制:最大文件描述符
mysql hard nofile 65535 # 硬限制
步骤 2:修改系统级限制(/etc/sysctl.conf)
vi /etc/sysctl.conf
# 添加以下内容
kernel.threads-max = 100000 # 系统总线程数上限
vm.max_map_count = 262144 # 内存映射限制
fs.file-max = 655350 # 系统总文件描述符
net.core.somaxconn = 65535 # 网络连接队列限制
# 生效配置
sysctl -p
步骤 3:重启 MySQL 使限制生效
systemctl restart mysqld
# 验证限制是否生效
su - mysql -c "ulimit -n && ulimit -u"
# 输出应为 65535 65535
方案 3:优化 MySQL 线程 / 连接参数(长期)
编辑 MySQL 配置文件(my.cnf/my.ini),调整参数适配服务器内存:
[mysqld]
# 连接参数优化(根据内存调整,16G 内存示例)
max_connections = 500 # 最大连接数,避免过高(16G 内存建议 500 以内)
thread_cache_size = 64 # 增大线程缓存,减少线程创建次数
thread_stack = 512K # 降低线程栈内存(若业务无复杂查询,默认 1024K 可降为 512K)
wait_timeout = 600 # 缩短空闲连接超时(默认 28800),释放连接
interactive_timeout = 600 # 交互式连接超时
# 内存优化(避免 MySQL 占满内存)
innodb_buffer_pool_size = 8G # InnoDB 缓冲池(16G 内存建议 50%-60%)
max_heap_table_size = 64M # 内存表大小
tmp_table_size = 64M # 临时表大小
修改后重启 MySQL 生效:
systemctl restart mysqld
方案 4:解决文件描述符 / 线程数限制
场景 4.1:文件描述符不足
# 1. 临时调整 mysqld 进程的文件描述符限制(需 root)
prlimit --nofile=65535:65535 -p $(pgrep mysqld)
# 2. 永久调整(修改 /etc/security/limits.conf 后,重启 MySQL)
场景 4.2:系统线程数达上限
# 临时增大系统总线程数上限
echo 1000000 > /proc/sys/kernel/threads-max
# 永久增大(修改 /etc/sysctl.conf,添加 kernel.threads-max = 1000000)
sysctl -p
方案 5:处理版本 / 内核兼容问题
# 1. 升级 MySQL 到稳定版本(如 8.0 最新版)
yum update mysql-community-server
# 2. 检查 OS 内核版本,若过旧则升级
uname -r # 查看内核版本
yum update kernel # 升级内核(需重启服务器)
方案 6:长期扩容(根治内存不足)
- 升级服务器内存:根据业务连接数 / 线程数,扩容物理内存(如 16G → 32G);
- 优化业务查询:减少长连接、慢查询,降低活跃线程数(如优化
Threads_running高的场景); - 启用连接池:应用端使用数据库连接池(如 Druid、C3P0),减少 MySQL 连接数;
- 读写分离:拆分读 / 写请求到不同 MySQL 实例,分散线程压力。
五、典型错误案例与修复
案例 1:内存不足导致线程创建失败
# 报错:
Can't create a new thread; if you are not out of available memory, you can consult the manual for a possible OS-dependent bug (error.:11)
# 排查:
free -h # 输出 Mem: 16Gi 15Gi 100Mi, Swap: 2Gi 2Gi 0Mi
SHOW STATUS LIKE 'Threads_connected'; # 输出 400(接近 max_connections=500)
# 修复步骤:
1. 清理系统缓存:sync && echo 3 > /proc/sys/vm/drop_caches
2. 临时扩容 swap:fallocate -l 4G /swapfile && chmod 600 /swapfile && swapon /swapfile
3. 优化 MySQL 参数:SET GLOBAL thread_cache_size = 64;
4. 验证:mysql -u root -p # 连接成功,可创建新线程
案例 2:系统线程数限制触发报错
# 报错:
Can't create a new thread; if you are not out of available memory, you can consult the manual for a possible OS-dependent bug (error.:35)
# 排查:
su - mysql -c "ulimit -u" # 输出 1024
SHOW STATUS LIKE 'Threads_created'; # 输出 10000+(线程创建数极大)
# 修复步骤:
1. 修改 limits.conf:添加 mysql hard nproc 65535
2. 修改 sysctl.conf:添加 kernel.threads-max = 100000
3. 生效配置:sysctl -p && systemctl restart mysqld
4. 验证:su - mysql -c "ulimit -u" # 输出 65535,连接恢复正常
案例 3:max_connections 过小导致连接数达上限
# 报错:
Can't create a new thread; if you are not out of available memory, you can consult the manual for a possible OS-dependent bug (error.:11)
# 排查:
SHOW VARIABLES LIKE 'max_connections'; # 输出 151
SHOW STATUS LIKE 'Max_used_connections'; # 输出 151
# 修复步骤:
1. 临时增大 max_connections:SET GLOBAL max_connections = 500;
2. 永久修改 my.cnf:max_connections = 500
3. 重启 MySQL:systemctl restart mysqld
4. 验证:SHOW VARIABLES LIKE 'max_connections'; # 输出 500,连接正常
六、预防措施
-
监控线程 / 连接状态:
- 监控
Threads_connected、Threads_running、Max_used_connections,超过 80% 阈值告警; - 监控服务器内存 /swap 使用率,阈值 85% 告警。
- 监控
-
优化线程复用:
- 增大
thread_cache_size(建议值:服务器 CPU 核心数 × 8),提高线程复用率; - 缩短
wait_timeout,释放空闲连接(非核心业务设为 300-600 秒)。
- 增大
-
系统资源预配置:
- 部署 MySQL 时,提前调整
limits.conf/sysctl.conf,设置nofile/nproc为 65535; - 根据内存大小合理设置
max_connections(16G 内存建议 500 以内,32G 建议 1000 以内)。
- 部署 MySQL 时,提前调整
-
业务层优化:
- 应用端使用连接池,控制并发连接数;
- 避免长连接占用(如定时关闭空闲连接),优化慢查询减少
Threads_running。
-
定期维护:
- 定期升级 MySQL/OS 内核,避免版本兼容问题;
- 定期检查线程创建数(
Threads_created),若增长过快,优化thread_cache_size。
总结
该报错的核心解决思路是:先通过 “内存→系统限制→MySQL 参数” 排查根因,再按 “紧急释放资源→调整参数→长期扩容” 解决。80% 的场景是内存不足或系统线程 / 文件描述符限制,只需临时释放内存、调整系统限制即可恢复;10% 是 MySQL 参数不合理,需优化连接 / 线程配置;剩余 10% 需扩容硬件或解决版本兼容问题。通过 “监控 + 参数优化 + 系统预配置” 的组合策略,可从根本上避免线程创建失败的问题。
MySQL线程创建失败解决方案

31万+

被折叠的 条评论
为什么被折叠?



