mysql在高并发场景下如何优化查询性能_mysql并发优化

1次阅读

加索引后查询仍慢的主因是索引未覆盖、顺序不当或隐式类型转换致失效;高并发下卡顿多由锁争用、元数据锁等待或主从延迟引发。

mysql在高并发场景下如何优化查询性能_mysql并发优化

为什么加索引后查询还是慢?

高并发下即使有索引,select 仍可能卡住,常见原因是索引未覆盖查询字段、索引列顺序不合理,或存在隐式类型转换导致索引失效。比如 WHERE user_id = '123'user_idint),mysql 会强制转为数字再比对,但某些版本下会放弃使用索引。

实操建议:

  • EXPLaiN forMAT=TREE 查看执行计划,确认是否走了预期索引,尤其注意 filtered 值是否远低于 100(说明实际扫描行数远超预估)
  • 联合索引要遵循「最左前缀」,且把高频过滤、区分度高的列放前面;排序字段若在 ORDER BY 中出现,尽量包含在索引末尾(避免 using filesort
  • 避免在索引列上做函数操作,如 WHERE date(create_time) = '2024-01-01' → 改成 WHERE create_time >= '2024-01-01' AND create_time

连接池配置不当会直接拖垮QPS

应用层连接池(如 HikariCP、Druid)若最大连接数设得过高,MySQL 的 max_connections 很快被耗尽,新请求排队等待,表现为连接超时或 Too many connections 错误;设得太低又会造成线程饥饿,吞吐上不去。

实操建议:

  • 先查 MySQL 实际峰值连接数:SHOW STATUS LIKE 'Threads_connected';,结合监控观察 95 分位值,max_connections 建议设为该值的 1.5–2 倍
  • HikariCP 中 maximumPoolSize 不宜超过 20–30(除非 IO 密集型且数据库硬件极强),并开启 connection-timeout(推荐 3000ms)防止阻塞扩散
  • 务必关闭自动提交(autoCommit=false),显式控制事务边界,避免长事务占用连接

读写分离没生效?可能是事务里混了写操作

很多业务以为只要用了主从架构,查询就会自动走从库——其实不然。一旦当前连接处于事务中(哪怕只执行了一条 SELECT),后续所有语句(包括读)都会路由到主库,否则无法保证一致性。

实操建议:

  • 检查应用代码:事务方法内是否夹杂了 INSERT/UPDATE/delete,哪怕只是日志表写入,也会让整个事务绑定主库
  • SELECT @@innodb_read_only; 在从库上确认只读状态是否开启(应返回 1),同时确认主从延迟 Seconds_Behind_Master 是否稳定在 100ms 内
  • 对强一致性要求不高的场景(如商品详情页浏览),可手动指定从库数据源,绕过框架默认路由逻辑

limit深分页为什么越翻越卡?

SELECT * FROM order WHERE status = 1 ORDER BY id LIMIT 10000, 20 这类语句在高并发下极易成为瓶颈:MySQL 必须先扫描前 10020 行,再丢弃前 10000 行,IO 和 CPU 开销随偏移量线性增长。

实操建议:

  • 改用游标分页(cursor-based pagination):记录上一页最后一条的 id,下一页查 WHERE id > 12345 AND status = 1 ORDER BY id LIMIT 20
  • 对必须支持跳页的后台系统,可建冗余字段(如 list_order)并维护有序序列,用等值查询替代 LIMIT offset
  • 禁止前端传入超大 offset(如 > 1000),API 层直接拦截并返回 400

真正卡住高并发的,往往不是单条 SQL 多慢,而是连接争抢、锁等待、主从延迟放大后的连锁反应。调优时优先看 SHOW PROCEsslIST 里有没有大量 Waiting for table metadata lockSending data 状态,这些信号比慢日志更早暴露系统瓶颈。

text=ZqhQzanResources