置顶SQL 与数据库排障 · 系列目录


SQL 与数据库排障 · 系列目录 叙事框架:一个慢 SQL 导致全站瘫痪的故事 总计 37 篇,已发布 14 篇,23 篇待完善 一、SQL / 索引类 ✅ 一个慢 SQL 打垮了整个服务?从 EXPLAIN 到索引优化全实战 ✅ 索引失效的 10 种场景:用 EXPLAIN 一个个验证 ✅ GR

主从切换失败?查查 GTID 集合——MASTER_AUTO_POSITION 的隐性陷阱


主从切换失败?查查 GTID 集合——MASTER_AUTO_POSITION 的隐性陷阱 场景:MC 自动切换后原主恢复,CHANGE MASTER TO MASTER_AUTO_POSITION=1 时报错 1872——master 已清除从库需要的 binlog 路径:GTID 自动定位协议

MySQL 主从延迟监控的顶级谎言:Seconds_Behind_Master


MySQL 主从延迟监控的顶级谎言:Seconds_Behind_Master 场景:从库 Seconds_Behind_Master=0,业务反馈刚写入的数据查不到。主从同步监控显示一切正常,实际数据延迟了 3 分钟。 路径:SBM 更新机制 → 时钟偏差多线程复制/relay log 堆积 →

改了行配置死锁没了账却乱了:MySQL 隔离级别选型血泪史


改了行配置死锁没了账却乱了:MySQL 隔离级别选型血泪史 以下分析基于 MySQL 8.0.32。 场景:一个高并发订单系统,改了一行 transaction-isolation=READ-COMMITTED,死锁消失了对不上账了 路径:死锁风暴 → RC 切换 → 对账异常 → 隔离级别本质 →

MySQL 同一个事务查了四次,数据反复横跳——快照读和当前读的边界


MySQL 同一个事务查了四次,数据反复横跳——快照读和当前读的边界 以下分析基于 MySQL 8.0.32。 场景:同一个事务内,同一张表,同一个 WHERE 条件——查了四次,数据量每次不一样 路径:四次查询 → ReadView 规则 → 快照读 vs 当前读 → 排查与重构 上篇讲了间隙锁死

两个 INSERT 同时死了,凶手是间隙锁


两个 INSERT 同时死了,凶手是间隙锁 以下分析基于 MySQL 8.0.32。8.0 的 data_locks 表和 5.7 结构不同,见文中标注。 场景:注册接口每秒报 200 次 DeadlockFoundWhenCommitting,两个并发事务插入同一个手机号 路径:错误日志 → SH

MySQL 没锁升级?一条 UPDATE 怎么把 5 万行全锁了


MySQL 没锁升级?一条 UPDATE 怎么把 5 万行全锁了 以下分析基于 MySQL 8.0.32。5.7 的 data_locks 表结构不同,见文

我写了个转账接口,MySQL 把我一个事务杀了——SHOW ENGINE INNODB STATUS 全拆解


我写了个转账接口,MySQL 把我一个事务杀了——SHOW ENGINE INNODB STATUS 全拆解 场景:两个并发转账事务,各更新两条记录,应用突然报 DeadlockFoundWhenCommitting 路径:SHOW ENGINE INNODB STATUS → LATEST DET

翻到 1000 页慢了 200 倍:OFFSET 不是翻页——是扫了再扔


翻到 1000 页慢了 200 倍:OFFSET 不是翻页——是扫了再扔 场景:分页列表翻到第 5000 页时接口从 50ms 飙升到 10 秒,ORDER BY id LIMIT 100000, 20 路径:EXPLAIN → rows=100020 → OFFSET 的执行本质 → 游标/子查询

少了个引号查询慢 80 倍:MySQL 隐式转换让索引废了


少了个引号查询慢 80 倍:MySQL 隐式转换让索引废了 场景:用户查询手机号接口从 100ms 飙升到 8 秒,phone 字段有索引但 EXPLAIN 显示 type=ALL 路径:EXPLAIN → type=ALL 但 key 列空 → SHOW WARNINGS → CAST(phone