EXPLAIN ANALYZE

RSS: https://explainanalyze.com/index.xml
专注于数据库性能优化与系统工程的技术博客。

一个未提交的只读查询让 MySQL 副本堆积十亿行历史版本

一篇 MySQL 排障实录:一个只读副本上未提交的读事务长期持有 read view,导致 InnoDB 无法 purge 旧行版本,历史版本堆积到约十亿行;每次读取都要走越来越长的版本链,副本复制也属于读负载,因此持续落后,落后时间已爬到 260,000 秒(约三天)且一周来不断上升。 主库流量没变(约 15k QPS、写速率平稳),排除了 backfill 等因素。文章强调修复只需一条 KILL,而定位到该杀哪个会话只需一条查询。 属于工程实践+一手现场排查,适合 DBA/性能调优读者深挖。
评论点赞收藏15 天前

MySQL 数据库只有 10GB,却撑爆了 200GB 磁盘

MySQL 数据库目录只占 10GB,但 200GB 磁盘已经用掉 184GB,df 和 du 对不上。 根因是端点安全代理进程一直开着 MySQL 的临时文件,这些文件被 MySQL 删掉后空间不释放,Linux 内核会将此进程名列出。 排查这类 df/du 不一致问题,用 lsof | grep deleted 可以定位。换了两次更大的硬盘只撑了几天,找到真实原因才解决。
评论点赞收藏18 天前

多查一列,页面读取从千级暴增至十六万级

给一个查询加一列,PostgreSQL 的页面读取从 1,020 暴增到 166,667。原因是 index-only scan 被打断,优化器被迫全表扫描。 订单表 orders 原本有 (customer_id, status, created_at) 的复合索引,查询只取索引里的列时走 index-only scan,1,020 页读完事。 加一列 order total 后该列不在索引里,每行都要回表读堆,超过阈值优化器直接放弃索引改为顺序扫描。 解决方案是扩展索引或缩小查询列,但扩展后的索引本身仍不够——还需要其他手段配合。
评论点赞收藏19 天前

32亿行表查询耗时100分钟,加一行代码后降至40毫秒

一条针对32亿行inventory.stock_counts表的报表查询从1小时43分优化到40毫秒,未改动表结构。核心方法是先看EXPLAIN ANALYZE执行计划,找到耗时那一行,再分别诊断"查询是否算了多余的东西"和"过滤条件是否匹配索引前导列"。 优化生效的前提是存在一个小集合可用来过滤;如果没有,只能加索引,而在这种规模的表上加索引既昂贵又不可逆。
评论点赞收藏27 天前

So You Want to Migrate to Postgres

TL;DR A data-technology migration is five migrations stacked on top of each other: the query surface, the coupling around it, the data itself, the operational model, and the long tail. Teams that esti...
评论点赞收藏53 天前

排序规则漂移:无声的索引杀手

MySQL 从 5.7 升级到 8.0 后,混用 utf8mb4_general_ci 和 utf8mb4_0900_ai_ci 排序规则会导致 JOIN 失败或索引失效。文章通过真实案例展示了隐式字符集转换如何使索引失效,并指出统一排序规则的修复方案可能因相等性定义改变而引发主键冲突。
评论点赞收藏69 天前

跨数据库连接:直到拆分时才看得见的耦合

同一MySQL实例上跨Schema的JOIN看似免费,实则是系统拆分的硬耦合。当业务需要水平拆分以扩展规模时,这些隐式关联会成为巨大的迁移障碍,且原有的引用完整性约束在拆分后失效。
评论点赞收藏81 天前

通过健康检查和监听脚本实现数据库自愈

利用Consul等服务的健康检查和Watch机制,实现数据库的窄范围自愈。提供了具体的工程思路,将基础设施监控能力转化为数据库运维方案,具有明确的实操价值和架构讨论空间。
评论点赞收藏84 天前

在坏数据写入之前:应对静默数据损坏的新思路

传统备份和复制机制旨在应对故障,但数据静默损坏会迅速被复制并保留在备份中,往往在数周后才被发现,此时已超出保留窗口。 文章提出解决数据损坏的核心在于建立数据溯源(provenance),通过追踪写入来源来识别并回滚错误的修改,而非仅仅依赖副本恢复。
评论点赞收藏85 天前

设计无需人工维护的数据库分区方案

文章指出按时间分区会导致主键变更和查询泄漏,建议改用主键ID分区并由后台服务自动管理边界。 这种方案让查询无需修改即可享受分区裁剪,同时通过服务动态对齐时间边界以支持数据保留策略。
评论点赞收藏91 天前

扩展模式而非实例:从根源解决系统性故障

文章指出大多数生产环境的修复只是针对眼前问题的临时补丁,虽然解决了当下问题,但导致同类故障反复发生。真正的解决方案需要在更高层面进行干预,通过改变模式来覆盖所有未来可能出现的实例。 这种思维方式要求工程师区分“偶发事件”与“系统性问题”,在实施修复前判断故障是孤例还是类问题,从而制定能根治而非仅缓解症状的策略。
评论点赞收藏102 天前

千刀万剐:那些绕过所有防护的 AI 数据库故障

文章指出,AI 生成的数据库代码往往在审查时看似正确,但随着数据积累导致性能崩溃或逻辑错误。这类“静默且不可恢复”的错误比明显的破坏性错误更难发现。 作者通过爬虫表膨胀和软删除漏计两个案例,说明现有审核流程无法拦截此类问题。建议通过业务级对账和限制 AI 访问敏感写入路径来缓解风险。
评论点赞收藏110 天前

窄工具与窄智能体:Agent 可靠性究竟从何而来

幻觉最少的 AI 智能体使用的是狭窄、专有的工具,并被赋予最小的任务范围。返回布尔值和延迟数的诊断端点优于通用的 SQL 查询接口。 拥有三个工具的受限智能体比拥有广泛工具的智能体更可靠,这揭示了 Agent 可靠性的真正来源。
评论点赞收藏123 天前

总是查询的问题(第五部分):磁盘有两个警报,而非一个

文章指出磁盘问题通常有两个警报:容量不足和性能下降。容量问题应通过分区归档解决,而非删除数据;性能问题则需优化覆盖索引以匹配访问模式。 云环境的自动扩展往往掩盖了底层的查询效率问题,导致资源浪费。作者强调从查询层面和Schema层面寻找长期有效的解决方案,而非依赖临时扩容。
评论点赞收藏126 天前

快速工程师悖论

文章指出工程师依赖AI加速工作,反而失去了通过慢工积累的判断力。这种速度带来了效率,却牺牲了代码的质量、安全性和可维护性。 作者认为,真正的工程能力来自于处理复杂问题的过程,过度依赖自动化会导致技能退化。
评论点赞收藏127 天前

总是查询的锅:第四篇——当排序发生溢出时

数据库内存告警通常不是因为整体内存不足,而是排序或哈希操作产生的瞬时、并发内存分配导致的。 文章解释了为什么实例级内存监控往往无法捕捉到这些危险的局部峰值,以及它们如何导致性能问题。
评论点赞收藏132 天前

总是查询的锅(三):当 CPU 满载时

关系型数据库 CPU 占满通常不是因为单个昂贵查询,而是廉价查询执行次数过多。慢查询日志和平均耗时排序往往忽略这一点,只有总执行时间视图能发现它。 作者通过客户端门户下拉菜单案例,展示了如何通过分析总执行时间来定位这种高频低耗的性能瓶颈。
评论点赞收藏134 天前

几乎总是查询的问题(二):故障排查步骤

本文介绍了一套可重复的数据库故障排查流程:先观察当前状态,再分类等待类型,接着缩小具体原因,最后采取行动。 作者强调这套逻辑顺序比使用的工具更重要,旨在帮助不常处理此类问题的工程师掌握排查技能。
评论点赞收藏136 天前

向 Agent 暴露数据:MCP 协议与专用 API 的抉择

文章对比了将数据暴露给 AI Agent 的两种方案:直接连接数据库或使用专用 API。作者认为在非生产环境中直接连接数据库便于探索,但在生产环境中应使用带有权限控制和行限制的保护层 API。 这反映了当前大模型应用开发中的实际工程权衡。
评论点赞收藏138 天前

登录芦苇

登录后关注作者、收藏内容和参与讨论。