查询没走索引,数据库直接被压垮了,崩溃现场真心惨烈
- 问答
- 2026-01-08 13:36:51
- 3
(引用来源:某电商平台资深工程师的技术复盘会议记录及内部沟通截图文字整理)
那天下午,系统监控大屏上,一条原本平缓如心跳的业务曲线,突然像发了疯的过山车,猛地向上蹿升,在几秒钟之内,又断崖式地跌到了零,紧接着,刺耳的警报声不是此起彼伏,而是像拉响了空袭警报一样,长鸣不止,整个办公区瞬间安静了一秒,然后就是一片“我这边超时了”、“页面打不开了”、“数据库连不上了”的惊呼声。
事情的起因,说起来有点让人哭笑不得,就是一个看起来非常普通的查询需求,市场部的同事想要分析一下最近三个月购买过某些特定品类商品、并且收货地址在某个区域的用户画像,用来做精准营销,这本来是一个常规需求,数据分析师小张写好了一个SQL查询语句,这个查询涉及好几张表,用户表、订单表、订单商品表、地址表,关联条件不少,筛选条件也挺复杂,在测试环境里,因为数据量很小,这个查询跑起来虽然有点慢,但两三秒也能出结果,大家觉得可能有点慢,但想到生产环境数据库性能强大,应该问题不大,加上业务方催得急,抱着侥幸心理,就准备在当天的业务低峰期上线这个查询任务。
下午三点,本该是流量最低的时候,小张在数据分析平台点击了“执行”,他万万没有想到,这一下点击,就像推倒了第一块多米诺骨牌,监控系统显示,就在查询发出去的那一刻,数据库主机的CPU使用率从平时的百分之二三十,瞬间飚到了百分之百,并且持续维持在红色警报线之上,磁盘I/O(输入输出)的指标也爆了,等待队列长度长得吓人。

为什么一个查询能有这么大的威力?后来我们才搞清楚,问题就出在那个“收货地址在某个区域”的筛选条件上,那个条件用的是对地址文本字段的模糊匹配,address LIKE '%某市某区某街道%'”,这种写法,数据库是无法使用索引的,因为它不确定你要找的内容具体在字段的哪个位置,这就好比让你在一本没有目录、也没有按任何顺序排列的百万页厚的电话黄页里,找出所有地址中包含“幸福里”三个字的人,你唯一的办法就是一页一页地翻,一行一行地看,这就是所谓的“全表扫描”。
而我们那张地址表,有上亿条记录,这个查询一执行,数据库就像那个翻黄页的倒霉蛋,不得不把上亿条记录全部从头到尾扫描一遍,对每一条记录的地址字段进行字符串匹配,这是一个极其消耗CPU和磁盘读写的操作,单个查询本身就已经不堪重负,更要命的是,它运行时间过长,锁占用了大量的资源。
这时,真正的雪崩开始了,平时运行顺畅的其他业务请求,比如用户登录、查看商品详情、生成订单等等,所有这些需要读写数据库的操作,全都卡住了,因为它们也需要访问数据库,而现在数据库所有的计算能力和磁盘读写能力都被那个“疯狂”的查询独占性地占用了,应用服务器发往数据库的连接请求开始堆积,得不到响应,很快,数据库的连接池被耗尽,新的请求根本连不上数据库了。

从应用层的角度看,就是整个网站都“僵死”了,用户点击任何按钮都没有反应,前端页面提示“服务器错误”或“网络连接超时”,订单无法下单,支付无法回调,连客服系统都因为无法查询用户信息而陷入半瘫痪状态,运营群里炸开了锅,不断有用户投诉电话打进来说网站用不了了。
运维同事的第一反应是重启数据库服务,试图快速恢复,但在那种极端负载下,连重启命令都执行得异常缓慢,好不容易重启成功,由于之前有大量未完成的交易和锁,数据库在启动后需要进行恢复操作,这个过程又持续了好几分钟,这几分钟,对于每分钟都可能损失大量真金白银的电商平台来说,简直是度秒如年。
整个故障从开始到完全恢复,持续了将近二十分钟,这二十分钟里,核心业务完全中断,事后粗略估算,直接的经济损失就是一笔不小的数目,更重要的是对品牌信誉和用户信心的打击。
复盘的时候,我们调出了当时的慢查询日志,那个“罪魁祸首”的查询语句赫然在列,执行时间长达十几分钟(如果不是数据库崩溃,可能还会更长),开发团队和运维团队的人都沉默了,一个在测试环境里看似“有点慢但能跑”的查询,在生产环境的真实海量数据面前,破坏力竟然如此惊人,它就像一颗潜伏的深水炸弹,平时看不见,一旦引爆,就能掀翻整艘大船,那次惨烈的崩溃现场,给所有人都上了一课:永远不要小看任何一个没有经过严格性能测试的数据库查询,尤其是在大数据量的生产环境下,索引的有无,真的能决定系统的生死。
本文由度秀梅于2026-01-08发表在笙亿网络策划,如有疑问,请联系我们。
本文链接:http://www.haoid.cn/wenda/76838.html
