MySQL常见报错分析及解决方案总结(29)---Can‘t create a new thread;if you are not out of available memory, you can

MySQL线程创建失败解决方案

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. 错误码含义

错误码系统含义触发场景
11EAGAIN(Resource temporarily unavailable)内存不足、线程数临时超出系统阈值,重试可能成功
35ENOSPC(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,连接正常

六、预防措施

  1. 监控线程 / 连接状态

    • 监控 Threads_connectedThreads_runningMax_used_connections,超过 80% 阈值告警;
    • 监控服务器内存 /swap 使用率,阈值 85% 告警。
  2. 优化线程复用

    • 增大 thread_cache_size(建议值:服务器 CPU 核心数 × 8),提高线程复用率;
    • 缩短 wait_timeout,释放空闲连接(非核心业务设为 300-600 秒)。
  3. 系统资源预配置

    • 部署 MySQL 时,提前调整 limits.conf/sysctl.conf,设置 nofile/nproc 为 65535;
    • 根据内存大小合理设置 max_connections(16G 内存建议 500 以内,32G 建议 1000 以内)。
  4. 业务层优化

    • 应用端使用连接池,控制并发连接数;
    • 避免长连接占用(如定时关闭空闲连接),优化慢查询减少 Threads_running
  5. 定期维护

    • 定期升级 MySQL/OS 内核,避免版本兼容问题;
    • 定期检查线程创建数(Threads_created),若增长过快,优化 thread_cache_size

总结

该报错的核心解决思路是:先通过 “内存→系统限制→MySQL 参数” 排查根因,再按 “紧急释放资源→调整参数→长期扩容” 解决。80% 的场景是内存不足或系统线程 / 文件描述符限制,只需临时释放内存、调整系统限制即可恢复;10% 是 MySQL 参数不合理,需优化连接 / 线程配置;剩余 10% 需扩容硬件或解决版本兼容问题。通过 “监控 + 参数优化 + 系统预配置” 的组合策略,可从根本上避免线程创建失败的问题。

评论 13
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值