直接改max_connections不能防oom,反而可能加剧风险;需结合global_connection_memory_tracking监控、connection_memory_limit熔断及max_user_connections隔离三者协同防御。

直接改 max_connections 不能防 OOM,反而可能加剧风险
单纯调高 max_connections 是典型误区。每个连接会分配 sort_buffer_size、join_buffer_size 等会话级内存,8GB 内存服务器设到 500+ 连接,仅缓冲区就可能吃掉 5GB 以上——还没算 InnoDB buffer pool 和系统开销。OOM kill 往往发生在内存峰值瞬间,不是连接数超限那一刻。
优先启用 global_connection_memory_tracking 做实时监控
MySQL 8.0.28+ 支持按连接粒度统计内存消耗,这才是防 OOM 的第一道防线:
- 执行
SET GLOBAL global_connection_memory_tracking = 1;开启全局追踪(需 SUPER 权限) - 查总量:
SHOW GLOBAL STATUS LIKE 'Global_connection_memory';—— 返回字节数,超过物理内存 70% 就该预警 - 查单个连接:
SELECT THREAD_ID, USER, CURRENT_MEMORY from performance_schema.memory_summary_by_thread_by_event_name WHERE CURRENT_MEMORY > 1048576;(>1MB 的连接) - 注意:InnoDB buffer pool 不计入此统计,它单独受
innodb_buffer_pool_size控制
用 connection_memory_limit 主动掐断高内存查询
对普通应用账号,设硬性内存上限比设连接数更治本:
- 给用户账号单独设限(不推荐全局设):
SET PERSIST_ONLY connection_memory_limit = 2097152;(2MB) - 该限制只对无 SUPER 权限的用户生效;有权限的账号(如 root)不受影响
- 一旦某条 SQL 预估内存超限,会立刻报错:
ERROR 1105 (HY000): Memory limit exceeded for this connection,连接被强制断开 - 必须搭配
global_connection_memory_tracking = 1才生效,否则只是摆设
用户级连接数限制仍是必要隔离手段
MAX_USER_CONNECTIONS 不解决内存问题,但能防止单个应用拖垮整个实例:
- 已有用户加限:
ALTER USER 'app_user'@'%' WITH MAX_USER_CONNECTIONS 30; - 新用户建时绑定:
CREATE USER 'api_user'@'%' IDENTIFIED BY 'xxx'; GRANT USAGE ON *.* TO 'api_user'@'%' WITH MAX_USER_CONNECTIONS 15; - 关键点:每个
User@Host组合独立计数,'app_user'@'192.168.1.%'和'app_user'@'localhost'必须分别设置 - 设为 0 表示不限,线上环境禁止;验证用:
SELECT User, Host, Max_user_connections FROM mysql.user WHERE User = 'app_user';
真正危险的不是连接数本身,而是连接背后那条没加 LIMIT 的全表 JOIN,或者没索引的 WHERE 子句。内存监控 + 查询熔断 + 用户隔离三者缺一不可,光调 max_connections 就像给油箱漏孔贴胶带。











