前阵子帮一个客户排查线上问题,他们的订单系统一到晚上八点就卡成PPT,数据库CPU直接飙到99%。我上去一看,好家伙,一个简单的列表查询居然扫了全表,数据量才二十万行。这就是典型的MySQL服务没优化到位,索引没建对,缓存配置也稀烂。今天就把这些实战经验掰开揉碎了讲讲,不是那种网上抄来的理论,全是踩过坑之后总结出来的干货。

先说说最基础的连接数配置。很多人以为maxconnections设得越大越好,结果把服务器内存撑爆了。MySQL每个连接都要占内存,默认的151连接数在大部分场景下其实够用,但你得看自己的实际业务。我见过最离谱的配置是有人把连接数设成2000,结果服务器直接OOM,连SSH都登不上去。正确做法是先用观察高峰期实际连接数,然后留出30%的余量。另外别忘了设置waittimeout和interactivetimeout,不然那些空闲连接会一直占着资源不释放。
索引优化这块,很多人有个误区,以为索引越多越好。实际上每个索引都会拖慢写入速度,还会占磁盘空间。我那个客户就是给所有字段都加了索引,结果写操作慢得跟蜗牛爬似的。真正该做的是分析慢查询日志,找出那些执行时间超过1秒的SQL,然后针对性地加索引。比如WHERE子句里经常用的字段、ORDER BY排序的字段、JOIN连接的字段,这些才是索引该待的地方。而且要注意最左前缀原则,复合索引别乱建,不然建了也是白建。
缓存配置这个坑最深。innodbbufferpoolsize这个参数,很多人直接照着网上教程设成8G,但你的机器总共才16G内存,这不是找死吗?正确做法是设为物理内存的50%-70%,还要留出足够内存给操作系统和其他进程。另外,querycachetype在MySQL 8.0里已经被移除了,还在用5.7的人也别太依赖它,并发高的时候反而会成为瓶颈。我一般建议把innodbbufferpoolsize设好,然后开启innodbbufferpoolinstances,让多个缓冲池实例并行工作。
慢查询日志绝对是排查性能问题的第一利器。默认情况下MySQL是不开启慢查询日志的,你得手动在配置文件里加上slowquerylog=ON和longquerytime=2。设成2秒是经验值,太短了日志会爆炸,太长了查不出问题。开启之后定期分析日志,用mysqldumpslow工具或者直接查performanceschema里的eventsstatementssummarybydigest表。我每次拿到新项目,第一件事就是开慢查询日志,连续跑一周,基本就能摸清这个系统的脾气了。
表结构设计这块,很多人不注意字段类型的优化。能用INT就别用VARCHAR,能用DATETIME就别用TIMESTAMP,能定长就用定长。我见过有人把订单金额存成VARCHAR(20),结果排序和比较全是坑。还有那种大字段TEXT/BLOB,能不放在主表就别放,拆出去单独建张附表,不然查询的时候这些大字段会把缓冲区塞得满满的。另外,分区表这个东西,很多人觉得高级就乱用,其实数据量没到千万级别根本没必要。
定期维护这块,OPTIMIZE TABLE和ANALYZE TABLE这两个命令很多人不知道或者懒得用。数据频繁增删改之后,表碎片会越来越多,索引也会变得不均衡。我一般建议每周跑一次OPTIMIZE TABLE,但要注意这个操作会锁表,最好在业务低峰期执行。还有那些历史数据,该归档的就归档,别让一亿条三年前的订单还躺在主表里,每次查询都拖累性能。
说说监控和预警。很多公司数据库挂了才知道出了问题,这是最被动的。我习惯用Prometheus加mysqld_exporter来做监控,把连接数、慢查询数、缓存命中率、磁盘IO这些关键指标都做成图表,配合Alertmanager设置告警阈值。比如说连接数超过80%就报警,慢查询超过每分钟10条就报警。这样问题还在萌芽状态就能发现,而不是等用户投诉了才手忙脚乱。
数据库优化这事儿,真不是一锤子买卖。你得把它当成一个持续迭代的过程,每次上线新功能、数据量变化、业务模式调整,都得重新审视这些配置。我的经验是每季度做一次全面体检,把那些执行计划变差的SQL揪出来重新优化。MySQL服务优化做得好的话,性能提升那是立竿见影的,系统稳定性也会上一个台阶。别指望有什么银弹,老老实实把这些基础功夫练扎实了,比什么都强。


