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' 暴涨


二、默认值与配置方法

默认值

版本

默认值

最大值

MySQL 5.7

50

65535

MySQL 8.0

151(自动 = max_connections

65535

配置方法

[mysqld]
# 永久配置
back_log = 500

动态调整(仅 Linux 有效):

SET GLOBAL back_log = 500;  -- 立即生效,重启失效

三、最佳实践:科学计算公式

黄金公式

back_log = max_connections × (1 - 连接池复用率)

经验法则

场景

推荐值

说明

短连接 PHP (无连接池)

max_connections × 0.8

连接频繁创建/销毁

连接池应用 (HikariCP)

max_connections × 0.1

连接复用率高

突发流量 (秒杀活动)

max_connections

峰值时队列缓冲

内网微服务

200 ~ 500

通常足够

通用推荐

[mysqld]
max_connections = 500
back_log = 500  # 与 max_connections 相等,简单安全

四、致命陷阱:OS 参数限制(⚠️ 必读)

back_log 被操作系统内核参数硬限制!
如果 OS 参数更小,MySQL 的配置无效。

必须检查的 OS 参数

OS 参数

作用

推荐值

检查命令

net.core.somaxconn

全局 accept 队列最大值

1024 ~ 65535

sysctl net.core.somaxconn

net.ipv4.tcp_max_syn_backlog

SYN 队列最大值

2048 ~ 4096

sysctl net.ipv4.tcp_max_syn_backlog

ulimit -n

单个进程文件句柄上限

65535

ulimit -n

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    *:3306
  • Send-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_connections

OS 层配套(必须):

# /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 限高下;队列满则丢,连接池是最佳。"

参数

推荐值

是否必须调 OS

back_log

max_connections

✅ 是

net.core.somaxconn

back_log

✅ 是

max_connections

500~1000

❌ 否

核心记忆点
back_logMySQL 与 OS 的契约,配置再大,OS 不点头也白搭。优先保证 net.core.somaxconn ≥ back_log