back_log 是 MySQL 监听 TCP 端口时的 连接请求队列长度 ,用于缓冲瞬间大量连接请求,防止高并发场景下 accept 队列溢出 导致的新连接丢失。
一、核心作用:TCP 连接缓冲区
三次握手与队列机制
客户端 SYN → 服务器 SYN-RCVD (进入 SYN 队列) → 客户端 ACK
↓
三次握手完成 → 连接进入 ACCEPT 队列 → 等待 accept() 系统调用
↓
MySQL 调用 accept() → 从 ACCEPT 队列取出连接 → 创建线程处理 back_log 控制的就是 ACCEPT 队列的最大长度。
队列溢出后果
队列满时:新连接的 ACK 会被丢弃或返回
ECONNREFUSED客户端表现:
ERROR 2003 (HY000): Can't connect to MySQL server错误定位:
SHOW STATUS LIKE 'Aborted_connects'暴涨
二、默认值与配置方法
默认值
配置方法
[mysqld]
# 永久配置
back_log = 500动态调整(仅 Linux 有效):
SET GLOBAL back_log = 500; -- 立即生效,重启失效三、最佳实践:科学计算公式
黄金公式
back_log = max_connections × (1 - 连接池复用率)
经验法则
通用推荐
[mysqld]
max_connections = 500
back_log = 500 # 与 max_connections 相等,简单安全四、致命陷阱:OS 参数限制(⚠️ 必读)
back_log 被操作系统内核参数硬限制!
如果 OS 参数更小,MySQL 的配置无效。
必须检查的 OS 参数
Linux 配置示例
# 临时生效
sysctl -w net.core.somaxconn=2048
sysctl -w net.ipv4.tcp_max_syn_backlog=2048
# 永久生效
echo "net.core.somaxconn = 2048" >> /etc/sysctl.conf
echo "net.ipv4.tcp_max_syn_backlog = 2048" >> /etc/sysctl.conf
sysctl -p # 加载配置
# 检查 MySQL 进程限制
cat /proc/$(pgrep mysqld)/limits | grep "Max open files"配置关系
实际生效的 back_log = min(
MySQL 配置的 back_log,
net.core.somaxconn,
/proc/sys/net/core/somaxconn
)五、监控与诊断
1. 查看当前队列状态
# 查看 Listen 端口队列情况(REPLACE 3306 为实际端口)
ss -ltn | grep :3306输出解读:
State Recv-Q Send-Q Local Address:Port
LISTEN 0 500 *:3306Send-Q:队列最大长度(应 =back_log)Recv-Q:当前队列中等待 accept 的连接数
2. MySQL 内部监控
SHOW STATUS LIKE 'Threads_connected';
SHOW STATUS LIKE 'Aborted_connects'; -- 重点关注
SHOW STATUS LIKE 'Connection_errors_internal';3. 诊断连接丢失
# 抓取 TCP RST 包(连接被拒绝)
tcpdump -i any port 3306 and tcp[tcpflags] & tcp-rst != 0六、常见问题与场景
问题 1:突发流量导致连接失败
现象:业务峰值时报 "Can't connect",Aborted_connects 激增。
排查:
# 检查队列是否溢出
ss -ltn | grep :3306
# Recv-Q 持续 > 0 说明队列已满解决:
[mysqld]
back_log = 1000 # 放大 2~3 倍问题 2:配置不生效
SHOW VARIABLES LIKE 'back_log'; -- 显示 500
ss -ltn | grep :3306 -- Send-Q 显示 128原因:net.core.somaxconn = 128 限制了 MySQL。
解决:按上文调整 OS 参数并重启 MySQL。
问题 3:与连接池的权衡
错误做法:back_log 设得很大,依赖队列缓冲高峰。
正确做法:应用层配置连接池,队列只是最后一道防线。
七、完整配置示例
[mysqld]
# 连接与队列配置
max_connections = 500
back_log = 500
# 超时配置
wait_timeout = 600
interactive_timeout = 600
# 线程配置
thread_cache_size = 50
# 8.0+ 数据字典缓存
table_open_cache = 6500
table_definition_cache = 2000
# 8.0+ 默认与 max_connections 对齐
# 若未显式配置,back_log = max_connectionsOS 层配套(必须):
# /etc/sysctl.conf
net.core.somaxconn = 2048
net.ipv4.tcp_max_syn_backlog = 2048
fs.file-max = 100000
# /etc/security/limits.conf
mysql soft nofile 65535
mysql hard nofile 65535八、高并发场景压测建议
# 使用 sysbench 模拟突发连接
sysbench --test=oltp_read_only \
--mysql-host=127.0.0.1 \
--num-threads=1000 \
--max-requests=1 \
--max-time=10 \
run
# 监控队列堆积
watch -n 1 'ss -ltn | grep :3306'调优目标:Recv-Q 峰值 < back_log × 0.8
九、总结口诀
"Backlog 防突发,OS 限高下;队列满则丢,连接池是最佳。"
核心记忆点:back_log 是MySQL 与 OS 的契约,配置再大,OS 不点头也白搭。优先保证 net.core.somaxconn ≥ back_log。
评论