多彩编程 多彩编程MZPH · CODE BLOG
ARTICLE DETAIL

文章详情

深耕前端与后端开发技术的一线实战笔记与踩坑复盘。

慢SQL治理实战:DBA、后端、SRE、技术负责人如何用好慢SQL工具

慢SQL治理实战:DBA、后端、SRE、技术负责人如何用好慢SQL工具 最近线上又出了一起由慢 SQL 引起的过载事故。凌晨 2 点某服务的定时任务跑了一条多表关联查询直接打满主库 IO紧接着依赖同一个库的订单接口全面超时值班的人爬起来翻监控、查日志、找 DBA 确认数据源权限折腾了一个多小时才定位到具体语句。事后复盘大家发现问题的关键不在“有没有监控”而在于慢 SQL 的发现和分析过程太依赖人工传递了。我后来把 NineData 社区版的慢 SQL 功能接入了几套环境实测了一段时间一个很直观的感觉是同一个功能不同角色打开它的方式完全不同收益也完全不同。这篇就聊聊 DBA、后端、SRE、技术负责人这几类角色到底谁更适合用以及各自该怎么用才能把价值发挥出来。先说结论方便没耐心看完的人这个功能没有“只适合某类人”的说法但不同角色使用它的深度和姿势差异很大。如果一定要排序运维压力最大的是 DBA日常收益最直接的是后端开发稳定性收益最明显的是 SRE而技术负责人适合把它当成管理抓手看趋势。下面展开聊。1. 先说清楚慢 SQL 功能到底解决了什么问题1.1 慢 SQL 从来不只是“执行慢”这么简单很多人一听到慢 SQL第一反应是“某条查询跑得慢超过阈值了”。这个理解没错但太浅了。一条慢 SQL 的价值不在于它自己慢了多久而在于它往往是系统故障链条的第一环。举个最常见的连锁反应某条 SQL 全表扫描执行 2 秒平时流量低的时候完全没感觉。等到大促或者业务高峰期并发一上来每个请求都要等这条 SQL 释放连接连接池很快被占满后续的所有请求都卡在获取连接上接口大面积超时网关开始报错最终用户看到的就是“系统挂了”。这时候再看那条 SQL2 秒的耗时只是表象真正的问题是它消耗的 IO、锁、连接资源把整个数据库拖垮了。慢 SQL 功能解决的正是这个“被发现”的问题。它不是帮你修 SQL而是把藏在数据库日志里的慢语句捞出来、聚合成可读的列表、按指标排序、甚至给出基础执行计划分析。有了它你不必再登录服务器用命令翻慢日志也不必盯着监控面板猜“是不是数据库有问题”。我实测下来NineData 社区版的慢 SQL 功能核心价值就是把“从日志里 grep”变成了“在界面上看列表”。慢查询时间、SQL 文本、来源库、执行次数、扫描行数这些关键字段一次性给全基础分析足够日常使用。1.2 传统排查方式为什么让人想骂人在引入这类工具之前团队排查慢 SQL 通常只有三条路。第一条登录数据库执行SHOW PROCESSLIST看当前有哪些查询在跑但问题是它只能看到“此刻正在执行的”一个 0.5 秒就结束的慢查询根本来不及捕捉。第二条开慢查询日志然后 SSH 到服务器上把 slow.log 拉下来用 grep、awk 慢慢筛费时费力而且日志文件几十 MB 的时候体验极差。第三条靠监控平台的数据库指标曲线比如 CPU 使用率飙高、连接数异常但指标只告诉你“数据库可能有问题”根本不会告诉你具体是哪条 SQL 导致的问题。真正让我觉得“需要这类功能”的瞬间是某次排查一条只在凌晨出现的慢查询。白天一切正常凌晨 3 点定时任务一跑CPU 立刻冲高但等我打开慢日志找的时候几百条记录里混着各种来源的查询没有排序、没有统计、没有去重肉眼根本分不清主次。这也是我认可 NineData 社区版的原因它把“被动等发现”变成了“主动给列表”。登录后按耗时排序扫描行数最高的几条一眼就能看到根本不需要一行一行在原始日志里找。而且社区版免费对很多没有采购商业数据库性能监控产品的中小团队来说属于零成本补上了一个很关键的盲区。2. DBA 的用法从“靠经验”到“拿数据说话”2.1 在 DBA 的工作流里它是什么角色DBA 是数据库的第一责任人也是慢 SQL 问题最直接的承受者。以前定位一条慢 SQL很大程度依赖个人经验先看当前连接状态、再看慢日志时间点分布、再猜可能涉及哪张表整个过程非常“手工作坊”。问题在于经验再丰富的 DBA 也不可能对每条业务 SQL 都了如指掌尤其是表结构变更、数据量增长之后执行计划可能在你没注意的时候悄悄恶化。慢 SQL 功能对 DBA 来说相当于一键把“可能有问题”的候选集缩小到了一个可控范围内。接入数据源后系统自动采集慢查询日志DBA 只需要定期打开列表按照耗时、扫描行数、执行次数排序就能快速锁定需要关注的语句。我在实际使用中养成了两个固定操作每天早上看一遍昨天的慢 SQL 列表按扫描行数降序排列抽查 Top 3 的执行计划每次大版本发布后第二天拉一次当天的慢 SQL 新增记录看有没有新引入的问题。这两个动作基本取代了过去“翻日志 猜”的流程。2.2 实操一次完整的慢 SQL 定位过程拿最近一次实际排查举例。某项目的订单查询接口在低峰期也会有零星超时DBA 打开 NineData 社区版慢 SQL 列表很快就找到了目标语句。SQL 长这样SELECT * FROM t_order WHERE user_id 123456 AND status 1 ORDER BY create_time DESC LIMIT 20 OFFSET 10000;列表里这条语句的 Query_time 是 2.3 秒Rows_examined 显示 46 万但 Rows_sent 只有 20 行。看到这个数字对比几乎可以立刻判断问题出在“扫描了大量数据但只返回了少量结果”。接着用工具里的执行计划功能确认发现这条查询确实没有走最优索引Extra 列还出现了 filesort。这条慢 SQL 的问题本质上是深分页加排序。OFFSET 10000意味着数据库要先把前 10000 行读出来扔掉再取第 10001 到 10020 行扫描行数随页码增长而线性膨胀。优化思路很直接要么改成游标分页用WHERE id 上一页最大 id代替 OFFSET要么加联合索引(user_id, status, create_time)让排序走索引。我选的是联合索引方案改动最小上线后这条 SQL 的耗时从 2.3 秒降到了 30 毫秒以内。这个案例里最值钱的不是“我给出了方案”而是“数据替我指出了方向”。没有扫描行数和执行计划这些数据我可能还要靠猜还不一定猜得准。2.3 DBA 视角的关键注意事项用这个功能时我踩过几个坑也总结了几条经验。第一不要把执行耗时当作唯一标准。一条 SQL 跑 0.5 秒但如果它一个月被调用一百万次累积的消耗可能比一条跑 5 秒但只调用十次的 SQL 大多了。所以优先级排序时要综合看耗时和扫描行数还要看执行次数。第二注意区分业务高峰和定时任务。白天高峰期的慢 SQL 和凌晨批处理产生的慢 SQL 完全不是一回事。高峰期出现说明正常业务流量下已经撑不住了凌晨出现往往是数据量增长或者任务调度重叠导致的。两种场景的优化策略完全不同混在一起看容易误判。第三社区版分析的是基础执行计划真正复杂的优化决策比如分区裁剪、索引合并、SQL 改写还是需要 DBA 结合表结构和业务去确认。工具是帮手不是替代者。3. 后端开发的用法从“被动背锅”到“主动发现”3.1 开发为什么总在慢 SQL 问题上吃亏后端开发大概是慢 SQL 问题里最憋屈的角色。SQL 虽然是自己写的但线上环境的真实执行情况开发往往要到事故发生之后才知道。DBA 不会提前通知“你的接口可能有问题”监控平台报警到群里的时候通常已经是接口超时、用户投诉的阶段了。这里的核心矛盾是开发写 SQL 时只关心业务逻辑对不对很少关心数据量增长到一百万、一千万之后执行计划会发生什么变化。等数据真的涨上去了问题才暴露而这个时候距离当初写代码可能已经过去了半年甚至写这段代码的人已经离职了。我自己作为开发出身最大的体会是慢 SQL 功能给了开发一个“提前自首”的机会。新功能上线前主动看一眼慢 SQL 列表里有没有新增的语句比被 DBA 在群里点名体面多了。3.2 把一条慢 SQL 映射到代码热点开发用慢 SQL 功能和 DBA 有个明显区别DBA 看到的是“哪条语句有问题”开发要回答的是“这条语句在哪个接口、哪个方法、哪个业务场景里被调用了”。我的做法是看到一条可疑慢 SQL 后先把表名记下来然后在代码仓库搜索匹配这颗表的 DAO 方法或者 Mapper 文件。再结合慢 SQL 出现的时间点比如“每天下午三点集中出现”“某个功能上线后才出现”就能进一步缩小范围。如果 SQL 里有明显的业务字段条件比如status 1 AND channel app还可以直接和业务日志对齐确认是哪条链路触发的。举个例子。一位同事上线了一个新的用户列表导出功能第二天慢 SQL 列表里就出现了一条导出任务的查询扫描行数很高。他一开始以为是导出数据量大所以慢后来仔细看执行计划发现是查询条件里有一个可空字段写成了WHERE deleted_at IS NOT NULL。这个写法本身没问题问题是这个字段上虽然有索引但IS NOT NULL让优化器选择了全表扫描。把写法改成deleted_at 0之后同样数据的执行时间大幅下降而且这段改动的验证完全可以在慢 SQL 列表上直接观察耗时变化。3.3 开发视角的实操建议新功能上线前主动查一次慢 SQL 列表确认没有新增的高耗时语句。别等线上出问题再查。看执行计划时重点看type是不是ALL全表扫描Extra里有没有Using filesort或Using temporary这两个是常见的性能杀手。联表查询要注意字段类型一致否则隐式类型转换会导致索引失效。varchar和int关联这种坑我见过太多次了。分页查询别写深 OFFSET数据量大之后一定要考虑游标分页或者至少加个排序字段的索引。不要只在本地小数据量下测试。本地两张表各 100 条数据什么 SQL 都快线上千万行才是真实考场。开发接入慢 SQL 功能后最明显的变化是接口变慢时不再只能干瞪眼而是自己先去慢 SQL 列表看一眼能解决的直接解决不能解决的带着数据去找 DBA沟通效率高了很多。4. SRE 的用法把慢 SQL 纳入稳定性治理4.1 SRE 为什么要关心 SQL 层面的东西SRE 的视角和 DBA、开发都不一样。DBA 管的是数据库实例本身开发管的是业务代码而 SRE 管的是整个系统的稳定性和容量。数据库作为全局依赖任何一条慢 SQL 都可能打爆一个共享资源池然后拖垮所有依赖方所以 SRE 必须把慢 SQL 当作稳定性治理的一个锚点。我接触过不少 SRE 同学他们平时看监控面板、看告警、看链路追踪但真正发生故障时最常问的一句话是“是不是数据库慢”在没有任何数据库语句级数据的情况下这个问题只能靠猜。慢 SQL 功能填的恰恰是这个空它提供的语句级数据让“数据库慢”从一句模糊的判断变成了一个可以被验证、被量化的事实。4.2 从慢 SQL 看容量与链路健康度SRE 用慢 SQL 功能核心是看趋势和关联性而不只是看单条语句。我需要强调的是单个慢 SQL 可能只是偶发波动但慢 SQL 数量的整体增长趋势往往暴露了容量问题。有一个很典型的场景某系统的主库 CPU 使用率每周都在缓慢爬升监控告警阈值一直没触发没人当回事。后来把慢 SQL 列表按周统计发现某条核心查询的执行次数和扫描行数随着业务放量在同步上涨。继续深挖发现这是同一张订单表因为数据量增长导致的索引效率下降。这时候再回头看 CPU 曲线一切都对上了。没有语句层面的数据SRE 很难把“CPU 上升”和“某条 SQL 开始变慢”这两件事联系到一起。另一个我比较推荐的用法是容量预估。看一条慢 SQL 的扫描行数增长曲线就能粗略判断这个查询在什么数据量级下会撑不住。比如当前 500 万行数据单次扫描 46 万行如果业务增速是每月 10%那大概什么时候会扫描到 200 万行就可以提前规划索引优化或者扩容而不是等故障发生再补救。4.3 SRE 视角的落地技巧长期看我建议 SRE 把慢 SQL 数据和一个简单的看板联动起来。故障复盘时把慢 SQL 列表截图存档作为“数据库慢”的直接证据。观察慢 SQL 出现的时间点和告警触发时间点是否吻合判断故障根因链。区分“业务慢”和“数据库慢”如果慢 SQL 出现时数据库 CPU、IO 都在低位那问题可能在应用侧锁等待如果资源被打满那 SQL 本身可能就是元凶。关注同一时段出现多条慢 SQL 的并发效应。单条慢 SQL 可能不算什么但几十条同时跑资源竞争会成倍放大影响。SRE 如果能把慢 SQL 数据接入自己的稳定性治理流程最大的好处是数据库故障从“玄学”变成了“有据可查”。5. 技术负责人的用法用慢 SQL 数据做技术决策5.1 技术负责人该看哪些指标技术负责人不需要逐条看 SQL 文本那是 DBA 和开发的事。负责人真正该关注的是规模、趋势、分布这三个层面的数据。规模就是每周产生多少条慢 SQL趋势就是连续四周是上升还是下降分布就是这些慢 SQL 集中在哪个服务、哪个库、哪类操作上。我见过一个很典型的例子。某团队两个项目中A 项目每周慢 SQL 有 60 多条B 项目只有个位数。A 项目负责人一直以为是自己业务复杂、数据量大但把慢 SQL 按服务模块一拆发现 70% 集中在两个老模块里而这些模块的代码已经很久没人维护了。这个数据直接指向一个管理问题技术债积累到一定程度后会转化为数据库资源的持续消耗。对负责人来说慢 SQL 列表不是一个“技术工具”而是一个“管理仪表盘”。它比代码 Review 更客观比线上故障更提前能够反映团队近期代码质量和系统健康度。5.2 如何让慢 SQL 数据变成团队改进项数据只有变成行动才有价值。我建议技术负责人在周会或者双周会上固定加一个五到十分钟的“慢 SQL 评审”环节。不追求大而全每次挑一到两条典型慢 SQL 讲清楚问题出在哪、为什么会出现、改了什么、效果如何。这个做法有几个实实在在的好处。第一它给团队传递了一个信号——代码的数据库性能是会被追踪的写 SQL 不是写完就行。第二它是很好的新人培训素材很多性能问题在教科书上理解不深落到自己系统里一条真实慢 SQL 上印象会非常深刻。第三它能为后续的技术投入提供决策依据。比如慢 SQL 数量持续居高不下且集中在某块业务那就需要考虑索引专项优化、读写分离甚至某张表的分库分表改造而不是简单粗暴地加内存、升 CPU。我之前还见过一个团队把“慢 SQL 数量”写进了季度目标里数据由工具按月统计目标从 200 条降到 80 条。这种量化改进方式比单纯喊口号“重视性能”有效得多。5.3 负责人视角的避坑提醒负责人用这类数据做决策时有几个坑要避开。第一别只看平均数和总量。峰值时段的慢 SQL 数量和半夜批处理的慢 SQL 数量业务含义完全不同。建议看趋势分类至少区分出“高峰时段”和“非高峰时段”两个口径去比较。第二慢 SQL 少不代表系统就是健康的。有些慢 SQL 一个月只出现一次但出现的那次往往就是故障的一次。比如稀有的数据倾斜场景、罕见的锁竞争这类问题单看数量波动发现不了需要结合具体语句和执行频率去看。第三别把压力全压给 DBA。很多慢 SQL 的根因在业务代码、在 SQL 写法、在表结构设计这些改不动的话DBA 再专业也只能帮你兜底。责任人要落到业务团队和开发 owner 身上。6. 四类角色的协作闭环一个慢 SQL 的完整生命周期6.1 角色分工对照表慢 SQL 功能看着简单但只有把不同角色的使用方式串联起来才能形成闭环。下面这张表是我整理的内部口径供参考。角色核心关注点代表动作主要产出DBA数据库实例性能、索引、执行计划定期巡检、分析 Top 慢 SQL、给出优化建议索引变更、参数调整、优化方案后端开发业务 SQL 正确性、代码热点定位定位代码位置、改写 SQL、改造分页逻辑代码变更、上线验证SRE系统稳定性、容量水位、故障复盘关联告警、看趋势、评估容量风险复盘报告、容量评估、告警优化技术负责人团队代码质量、资源投入优先级周会评审、制定改进目标、推动专项改进清单、资源决策这个表的分工逻辑很简单发现靠工具定位靠 DBA修复靠开发复盘靠 SRE决策靠负责人。任何一环断掉慢 SQL 治理都会回到以前那种“靠人肉追踪”的状态。6.2 一条慢 SQL 的完整流转示例拿一个真实的虚拟场景来说明某系统周报功能每周一早上生成上一周的数据汇总最近连续三周都出现了数据库 CPU 毛刺。周一早上监控告警触发。SRE 打开 NineData 社区版慢 SQL 列表发现一条聚合统计 SQL 扫描行数异常于是截图发到故障群并把问题挂为“待排查”。后端开发看到语句后去代码仓库定位确认这是周报服务里的一个统计查询。DBA 介入查看执行计划发现统计 SQL 关联的三张表里一张大表的关联字段缺少索引建议增加联合索引。开发提交变更DBA 审核并在低峰期执行索引变更。下周一再看慢 SQL 列表这条语句已经消失SRE 把结论写进复盘记录负责人则在周会上确认类似统计查询还有没有别的遗漏。整个流程里工具承担的是“提供数据事实”的角色。没有这个事实SRE 不会知道该找哪个开发开发不会知道自己线上 SQL 有问题DBA 也不会轻易给出索引建议。6.3 团队落地时的关键约定最后分享几条团队落地时的约定都是实操中试出来的经验。接入数据源时一定用只读账号慢 SQL 分析只需要读权限就能完成不要给业务账号或者高权限账号。明确查看口径。看生产库还是测试库要不要排除系统库不同口径下的数据差异会很大团队内部先说清楚否则讨论时容易各说各话。约定响应时效。比如 P0 级慢 SQL导致接口大面积超时的两小时内必须有人响应P1 级频繁出现在 Top 列表的两个工作日内给出结论。时效不约定问题容易在群里不了了之。工具职责边界要讲清楚。NineData 社区版负责“发现和分析基础信息”具体的变更执行、效果验证还是要走现有的数据库变更流程避免流程混乱。7. 使用 NineData 社区版慢 SQL 的实操心得与坑7.1 接入和基础配置接入过程不复杂核心是把数据库实例作为数据源添加进去并确保数据库开启了慢查询日志采集。社区版面向个人和小团队注册后添加数据源就能看到慢 SQL 列表整体配置门槛不高。我在接入时最看重两个配置项。第一个是慢查询阈值。数据库默认的long_query_time通常是 10 秒这个标准对绝大多数互联网应用来说太宽松了10 秒的 SQL 在线上已经能造成严重影响了。建议结合自己业务的接口耗时要求来设置一般压到 1 秒到 2 秒比较合理。第二个是保留周期。先采集一周的数据量足够看出工作日和周末的差异也够统计趋势采集太短看不出规律。7.2 常见问题速查现象可能原因排查方向列表中看不到任何慢 SQL实例慢查询日志未开启或者阈值设得太高确认慢日志开关和 long_query_time 配置展示时间和数据库本地时间不一致时区设置不同统一各环节的时区配置慢 SQL 数量比自己的预期多很多存在大量扫描行数高但耗时不高的语句重点看扫描行数而不是只看耗时同一条 SQL 反复出现多次同一模板不同参数值会各自计一次按 SQL 指纹去重关注模板整体趋势短时间出现大量慢 SQL 但语句不相关可能是连接池打满或锁等待引发连锁反应结合数据库当时的连接数和锁信息交叉判断7.3 最后几个使用心得这套功能我实际用了大概三周最大的体会是工具解决的是“发现”问题而不是“解决”问题。NineData 社区版可以高效地把慢 SQL 从日志里捞出来、展示清楚但它不会替你做索引设计也不会替你改写业务 SQL。最终落地的优化还是要靠人。我个人的一个习惯是每周五下午花二十分钟过一遍本周慢 SQL 列表按扫描行数排序挑一两条印象最深的记录看看执行计划。这个习惯看起来不起眼但坚持下来你会对自己系统的数据增长规律、索引失效模式、SQL 写法问题建立非常具体的感知。这种感知是任何监控面板和告警都替代不了的。如果要从四类角色里选一个“最适合优先接入”的人我的建议是从 DBA 开始或者从团队里最关心数据库性能的那个人开始。接入之后把慢 SQL 列表分享给开发和 SRE让不同角色都养成定期查看的习惯。等大家都开始“用数据说话”而不是“凭感觉争论”的时候这个功能的价值才算是真正被吃透了。
返回列表