MySQL为什么扛不住高并发?

MySQL是大型架构核心,下面我详解MySQL为什么扛不住高并发@mikechen

连接数与线程模型限制

MySQL采用每个连接,对应一个线程(或线程池)的模型。

MySQL为什么扛不住高并发?-mikechen

max_connections 默认只有151,生产环境虽可调高到几千,但每个连接都会消耗内存(连接缓冲区、排序缓冲区等)。

并发连接过多时,CPU会进行大量线程上下文切换(Context Switch),开销远大于实际SQL执行。

典型表现

Too many connections 报错;

CPU负载高,但实际吞吐量反而下降(抛物线效应);

show processlist 看到大量 Sleep 或 Waiting for table flush 的线程。

缓解思路:连接池(Druid/Hikari)+ 读写分离 + 限流,但无法根本解决单机限制。

 

锁竞争与并发控制瓶颈

高并发系统,最容易出现:锁冲突。

为什么数据库需要锁?因为:多个线程,可能同时修改同一条数据。

MySQL为什么扛不住高并发?-mikechen

比如:库存扣减。

UPDATE stock
SET num = num - 1
WHERE id = 1;

如果:

1000 人同时抢购;

没有锁;

库存可能直接扣成负数。

当大量并发请求同时修改同一行数据或相邻数据时,会产生严重的锁竞争(Lock Contention)。

此时,原本的并发请求会因为等待锁释放而变成“排队执行”。

如果出现长事务,后续的所有请求都会堆积,最终导致连接池耗尽,触发 Too many connections 报错。

 

 

磁盘I/O瓶颈

MySQL 的 InnoDB 存储引擎使用 B+ Tree 组织数据。

这种结构在面对随机写入或大规模读取时,对磁盘 I/O 极其敏感。

MySQL为什么扛不住高并发?-mikechen

尽管有 Buffer Pool 缓存,但当并发量超过缓存承载能力时,系统必须频繁进行磁盘随机读写。

磁盘(即便是 NVMe SSD)的 IOPS 也是有上限的。

在高并发更新场景下,B+ Tree 的页分裂(Page Split)和合并会导致严重的 I/O 阻塞。

典型表现

innodb_log_waits 升高;

iostat 显示 %util 接近100%;

TPS(Transactions Per Second)无法继续提升。

 

查询执行与数据量膨胀

比如:单表数据量过大(>2000万行经验值)后,B+Tree索引层级增加,查询和更新效率下降。

MySQL为什么扛不住高并发?-mikechen

统计信息不准、执行计划错误,进一步放大问题。

典型表现

慢查询日志(Slow Query Log)大量记录;

CPU使用率高企(计算型瓶颈);

随着数据增长,性能线性或指数级下降。

缓解思路:SQL优化 + 索引 + 读写分离 + 缓存(Redis) + 分库分表 + 冷热数据分离。

评论交流
    说说你的看法