亿级QPS下,MySQL 如何调优?

MySQL是大型架构核心,下面我详解MySQL调优@mikechen

优化 SQL 与索引(先把“每次查询”做轻)

每次请求尽量少扫数据、少做排序/临时表、少锁行,这一步往往就能把 QPS 提高数倍。

开慢查询日志 + 抓 Top N:打开 slow_query_log、调整 long_query_time(如 0.5–1s)。

用 mysqldumpslow、pt-query-digest 找出最耗时/最频繁的 SQL。然后对这些 SQL 做重点优化。

亿级QPS下,MySQL 如何调优?-mikechen

索引设计:

为 WHERE / JOIN / ORDER BY / GROUP BY 常用组合建复合索引,尽量覆盖查询(覆盖索引)。

避免低选择性字段单独建索引(如状态位),控制单表索引数量(一般不超过 5 个高价值索引)。

改写查询:

禁用 SELECT *,只查必要列,减少 I/O 和网络传输。

复杂多表 JOIN 尝试拆成多次简单查询 + 应用层聚合,或适当做字段冗余,换 CPU 计算来减 DB 压力。

尽量避免大范围模糊查询(%xxx)、未索引排序导致的 Using temporary / Using filesort。

控制大事务与锁:

写操作尽量批量化(如批量 UPDATE/INSERT),减少事务提交次数与锁竞争。

把长逻辑搬到异步任务/队列,保证在线事务尽量短。

 

调 InnoDB & 连接参数(让单机接近可承受上限)

在常见的 8 核 32G + SSD 上,通过合理参数和 IO 优化。

亿级QPS下,MySQL 如何调优?-mikechen

内存与缓冲池:

innodb_buffer_pool_size 设置为物理内存 60%–75%(专用 DB 甚至 70%–80%),保证热数据大部分在内存中。

合理设置 innodb_buffer_pool_instances(如 8–16),减少互斥锁争用。

日志与刷盘:

innodb_log_file_size 适度加大(如单个 1–2GB),减少 checkpoint 频率,提升写入吞吐。

根据业务在延迟和数据安全之间权衡 innodb_flush_log_at_trx_commit(高并发写常见是 2)。

 

引入缓存层削峰(让真正打到 MySQL 的 QPS 掉一半以上)

绝大多数业务想要“万级 QPS DB 仍很轻松”,离不开 Redis 等缓存削峰,把冷热分离。

亿级QPS下,MySQL 如何调优?-mikechen

读缓存:

热点数据如商品详情、配置、排行榜等放 Redis/Memcached,应用先查缓存,miss 再查 DB 并回填。

通过业务统计,找出 QPS 最高、结果可缓存的接口(如某些 GET 接口),把它们优先缓存,通常可以将 DB QPS 压到原来的 1/3~1/10。

写 + 缓存策略:

写 DB 后同步或异步删除/更新缓存,保证数据最终一致。

注意缓存击穿、穿透、雪崩:对热点 key 设置互斥锁重建、预热、合理过期与降级策略。

多级缓存:

Web 层本地缓存 + Redis +(可选)DB 结果缓存组合,进一步减少落到 MySQL 的请求比例。

万级 QPS 时,如果能让“打 DB 的只剩 10%–30%”,MySQL 压力会小很多,调优空间也更大。

 

架构扩展:读写分离、分库分表与横向扩容

当单机 + 缓存 + SQL 调优仍接近瓶颈时,就要用架构手段把压力拆散。

亿级QPS下,MySQL 如何调优?-mikechen

读写分离:

主库专门负责写,从库承担读压力,通过 ProxySQL / MySQL Router / 自研中间件做读写路由。

读多写少场景下,多加几台只读实例就能平摊万级 QPS 的大量读请求;注意从库延迟和一致性策略(如读主 or 读从)。

分库分表:

单表数据过千万、上亿时,按用户 ID 或业务 ID 做水平切分(如 user_id % 16),结合 ShardingSphere 等中间件透明路由。

分片数与目标 QPS 成近似线性关系:比如某云厂在 32 分片规模下达到了 80 万 QPS,再加分片继续线性提升到百万级。

mikechen睿哥

10年+一线大厂架构经验,资深技术专家,就职于阿里、淘宝等一线大厂,操盘多个亿级数据量大厂核心项目。

评论交流
    说说你的看法