问题出现得很突然,日志倒是留得挺全。一台 4 核 4G 的 CentOS 7.9 跑 MySQL 8.0,业务并发一上来就报 Can’t create thread to handle request (errno 11),连接数是慢慢涨上去的,可报错集中在同一分钟内爆发。

刚开始盯着「内存紧张时创建线程同样会失败,报错文案却不提内存」,折腾了半个多小时,排掉了。

这类报错背后常见的原因有几处,逐个排除就行。MySQL 是一个连接一个线程,连接数上去线程数就跟着上去,撞到进程数上限。少数情况下是systemd 给 mysqld 的 LimitNPROC 偏低,ulimit 里的值不是实际生效值。

还有一种情况,连接池配置了很大的最小空闲数,实例一启动就把线程铺开。

上来先看实例允许的连接数与当前值

mysql -e 'show variables like "max_connections"; show global status like "Threads_connected";'

接着确认进程真正拿到的进程数上限

cat /proc/$(pidof mysqld)/limits | grep -i processes

再往下把 unit 里的进程数与文件数一起放开

printf '[Service]\nLimitNPROC=65535\nLimitNOFILE=65535\n' > /etc/systemd/system/mysqld.service.d/limits.conf && systemctl daemon-reload && systemctl restart mysqld

复压确认还会不会报错

tail -200 /var/log/mysql/error.log | grep -c "Can't create thread"

怎么算真的好了,看的是同一批现象。压测期间错误日志不再出现 Can’t create thread,Threads_connected 稳定在三百以内,接口错误率回到零。

提醒一点。放开进程数之前先算内存,一个连接几十 M 的缓冲,线程数放得太开会把机器拖死。线上能稳定复现的问题都不算难,难的是只在大流量下才出现的那种。

作者 9823189