MySQL 8.0 默认 max_connections=100 不足以应对真实并发,易触发 ERROR 1040;盲目调大将加剧内存压力甚至引发 OOM,须结合连接泄漏排查、wait_timeout 优化、admin_port 启用及 MAX_USER_CONNECTIONS 隔离综合治理。

默认max_connections=100根本扛不住真实并发
MySQL 8.0 默认 max_connections=100,这不是保守,是“对单机开发友好,对生产致命”。一个电商接口每秒 200 次请求,哪怕用连接池复用,若池大小设为 50、超时设为 30 秒,瞬时连接数就可能冲到 150+——还没算后台任务、监控探针、运维脚本的连接。一旦打满,新请求直接报 ERROR 1040 (HY000): Too many connections,不是慢,是彻底拒绝服务。
调大max_connections反而加速OOM崩溃
盲目把 max_connections 改成 500 或 1000 是最危险的操作。每个连接默认分配 sort_buffer_size(256KB)、join_buffer_size(256KB)、read_buffer_size(128KB)等会话级内存,500 连接光缓冲区就吃掉近 300MB;再叠加 innodb_buffer_pool_size(通常占物理内存 70%),8GB 机器极易触发 Linux OOM Killer 杀掉 mysqld 进程——比连接数满更难恢复。
-
SHOW GLOBAL STATUS LIKE 'Global_connection_memory'才是真实内存水位,不是Threads_connected -
connection_memory_limit必须配合global_connection_memory_tracking = 1才生效,否则只是摆设 - root 用户不受
connection_memory_limit限制,但普通应用账号必须设,否则高内存 SQL 会拖垮整实例
真正压垮数据库的从来不是连接数本身
连接数爆满只是表象,背后是没加 LIMIT 的全表 JOIN、WHERE 字段没索引、事务未提交卡住连接、应用层连接未 close 等问题。一个 Sleep 状态连接占用内存少,但一个执行中的慢查询可能独占 200MB 内存并锁住行——这时杀连接不如杀 SQL。
- 查高内存连接:
SELECT THREAD_ID, USER, CURRENT_MEMORY FROM performance_schema.memory_summary_by_thread_by_event_name WHERE CURRENT_MEMORY > 1048576 - 查事务外空闲连接:
SELECT ID, USER, COMMAND, TIME, STATE FROM information_schema.PROCESSLIST WHERE COMMAND = 'Sleep' AND TIME > 60 -
KILL CONNECTION比KILL更安全,它只断开连接不强制终止语句执行
MAX_USER_CONNECTIONS不是可选配置,是隔离底线
不设 MAX_USER_CONNECTIONS,等于让所有应用共享同一根绳子。一个下游服务 bug 导致连接疯涨,整个库就挂。必须按用户粒度硬隔离:
ALTER USER 'order_svc'@'10.0.1.%' WITH MAX_USER_CONNECTIONS 40CREATE USER 'report_user'@'%' IDENTIFIED BY 'xxx' WITH MAX_USER_CONNECTIONS 5- 注意:不同 host(如
'app'@'192.168.1.10'和'app'@'192.168.1.11')要分别设,MySQL 不合并统计


















