back_log仅影响TCP连接排队,不解决锁重试;锁等待超时由innodb_lock_wait_timeout、索引缺失、长事务等引发,需优化SQL、加索引、拆分事务并调低超时值。

back_log 参数本身不解决锁重试问题,它只影响连接建立阶段的请求排队能力。锁重试(如 Lock wait timeout exceeded)发生在事务执行过程中,由 innodb_lock_wait_timeout、并发冲突、索引缺失或长事务引发,和 back_log 完全无关。
如果你在高并发写入时频繁看到锁等待超时,先确认是不是误把连接排队问题当成了锁问题——比如看到大量 unauthenticated user 状态进程,那才是 back_log 不足的典型表现;而真正锁重试时,SHOW PROCESSLIST 里会显示大量 Updating 或 Locked 状态,并伴随 Waiting for table metadata lock 或 Waiting for row lock。
怎么判断是 back_log 不足还是锁争用?
看 SHOW PROCESSLIST 输出里的状态和来源:
- 如果大量连接卡在
Connecting或unauthenticated user,且客户端报错是连接拒绝(如Can't connect to MySQL server或系统级Connection refused),说明 TCP 连接队列溢出 →back_log或系统内核参数tcp_max_syn_backlog不够 - 如果连接已建立,但线程长时间停留在
Updating、Locked、Waiting for ... lock,且错误日志出现Lock wait timeout exceeded→ 是 InnoDB 行锁/元数据锁争用,需调innodb_lock_wait_timeout、优化 SQL、加索引、拆事务 - 检查
SHOW STATUS LIKE 'Threads_connected'是否接近max_connections;若远低于该值但仍有连接失败,基本可排除连接数限制,指向back_log或 OS 层限制
back_log 设置不当的真实后果是什么?
它只控制「已完成三次握手但尚未被 mysqld 接受处理」的 TCP 连接请求数量,本质是内核 SYN queue 的消费者缓冲区。
-
back_log值 > 当前系统/proc/sys/net/ipv4/tcp_max_syn_backlog(例如 1024)→ 实际生效值 = 系统上限,多余配置无效 - Linux 推荐设为 ≤ 512;设到 900 在多数云主机上反而触发内核丢包,表现为偶发性连接失败,而非稳定超时
- MySQL 5.6.6+ 默认值是
50 + max_connections/5(上限 900),但若max_connections = 3000,默认算出来是 650 → 很可能超出系统限制,需同步调大tcp_max_syn_backlog - 修改后必须重启 MySQL 生效(
SET GLOBAL不支持动态改back_log)
真正减少锁重试该调什么?
锁重试不是靠增大排队能力能缓解的,它需要缩短单次锁持有时间、降低冲突概率:
- 把
innodb_lock_wait_timeout从默认 50 调低(如 5–10),让冲突事务快速失败,避免堆积;注意应用层要捕获Deadlock found和Lock wait timeout并重试 - 确保 WHERE 条件走索引(用
EXPLAIN验证),否则会升级为表锁或锁全表间隙 - 避免长事务:不要在事务里做 HTTP 请求、文件读写、sleep();SELECT 也尽量不在事务中执行
- 写操作尽量按主键顺序进行,减少行锁交叉;批量更新拆成小批次(如每次 500 行)
- 检查是否有未提交事务长期占用锁:
SELECT * FROM information_schema.INNODB_TRX ORDER BY TRX_STARTED LIMIT 5;
back_log 是连接入口的“门厅容量”,而锁重试是“办公室内部抢工位”。调大门厅不会让工位变多,也不会让人更快坐下——它只防止人在门口挤散。真要减少抢座位,得增加工位(索引)、规范入场流程(事务设计)、或者让等不及的人早点离开(降低 innodb_lock_wait_timeout)。最容易被忽略的是:很多人改完 back_log 发现锁问题还在,就以为参数没生效,其实根本没对症。


















