z35资讯网 · 资讯快报
快报 · 一手资讯即时送达
实时快报

这几年踩过的数据库坑,我整理成了一份经验分享

这几年踩过的数据库坑,我整理成了一份经验分享-合肥z35资讯网

时尚 2026-11-14 20:12:48 阅读

前阵子凌晨两点被电话叫醒,监控报警说订单库 CPU 打满,接口超时率飙到 30%。我迷迷糊糊连上跳板机,第一件事就是 show processlist,看到一个跑了 40 多秒的 SQL 卡在那儿。处理完复盘,原因特别朴素:where 条件里的字段类型和索引字段类型对不上,隐式转换直接把索引干废了。这事我在团队里讲了三遍,干脆写下来,省得下次再有人踩。

慢查询基本都是自己写出来的

很多人觉得数据库慢是硬件不行,该加内存加内存。我遇到的情况里,九成以上是 SQL 本身的问题。explain 是我用得最多的命令,重点看三列:type 是不是 ALL,key 是不是 NULL,rows 扫了多少行。只要 type 出现 ALL,基本可以判定全表扫描,数据量一上来就完蛋。

这几年踩过的数据库坑,我整理成了一份经验分享

还有个坑是联合索引的最左前缀。我们有个查询按 status 和 create_time 过滤,索引建的是 (create_time, status),结果 status 用不上,只走了前半段。调换顺序之后,同样的 SQL 从 1.2 秒降到 30 毫秒。现在我上线任何 SQL 之前,都会在测试库 explain 一遍,看执行计划对不对,这个习惯帮我省了太多半夜爬起来的时间。

这几年踩过的数据库坑,我整理成了一份经验分享

索引不是越多越好

刚工作那会儿我觉得索引多多益善,每个查询字段都加一个。后来发现写入性能掉得厉害,一条 insert 要同步更新七八个索引,批量导入 10 万条数据跑了快半小时。删掉几个没用的索引之后,时间缩到 6 分钟。我现在的做法大概是这样:

这几年踩过的数据库坑,我整理成了一份经验分享

  • 单表索引控制在 5 个以内,超了就说明查询模式太散,该考虑拆表了
  • 联合索引把区分度高的字段放左边,user_id 一定要排在 status 前面
  • 定期查一下没被用过的索引,直接删,别舍不得
  • 性别、状态这种只有几个值的字段,单独建索引意义不大

分库分表别急着上

单表到千万级,很多人第一反应就是分库分表。我的经验是,先看能不能靠归档和改查询扛过去。我经手过一个 8000 万行的表,把两年前的历史数据归档到冷库,热表只剩 600 万行,性能立刻就回来了,改造成本几乎为零。真要拆的时候,分片键的选择比中间件选哪个重要得多,选错了后面想改,得掉一层皮。

连接池也是重灾区。我见过把 maxPoolSize 设成 200 的,觉得越大越稳,结果数据库连接数被占满,其他服务全连不上。一般 10 到 20 就够用,具体数值拿 QPS 乘上单条 SQL 平均耗时估一下,别拍脑袋。

备份和监控是最后的底线

我见过一次误删数据的现场,运维手一抖 delete 少写了 where,整个表清空。好在有 binlog,配合备份恢复了 90% 的数据,剩下 10% 靠业务日志一点点补,折腾了两天。从那之后我坚持三件事:备份一定要定期做恢复演练,没演练过的备份等于没有;慢查询日志必须开,long_query_time 设 1 秒;主从延迟要单独监控,别等读到的数据是旧的才发现问题。

说到底,数据库这块没有什么一招鲜的技巧,都是靠一次次出事攒出来的经验。我的判断是,把 SQL 写好、索引建对、备份做扎实,能解决 90% 的线上问题,剩下的再谈架构升级也不迟。

相关阅读

更多 ›