MySQL InnoDB 缓冲池与刷脏机制实战:从 free list、flush list 到 page cleaner 的参数调优
MySQL InnoDB 缓冲池与刷脏机制实战:从 free list、flush list 到 page cleaner 的参数调优晚高峰,订单库的 RT 突然从 20ms 飙升到 500ms,监控显示磁盘 IO 使用率飙到 100%,但 QPS 并没有明显上涨。登录服务器,SHOW ENGINE INNODB STATUS 一看:Modified db pages 占到了 Buffer pool 的 85%,Free buffers 只有几十个,而 Buffer pool hit rate 却高达 99.8%。
这个现象很有迷惑性:命中率这么高,为什么还会性能抖动?答案藏在 InnoDB 的脏页刷盘机制里。这篇文章我会从缓冲池内部结构讲起,结合真实的故障排查过程,给出可落地的参数调优方案。
这次故障也让我意识到:监控指标只是表象,理解内部机制才能真正定位问题。这是我从一个只会背参数的 CRUD 工程师,开始向内核级开发者转变的起点。
1. InnoDB 缓冲池内部结构:三张链表的分工InnoDB 缓冲池(Buffer Pool)是内存中的一块区域,用来缓存数据页和索引页,避免每次 ...
商品宽度与深度:SKU 数量管理、长尾与爆款的取舍
商品宽度与深度:SKU 数量管理、长尾与爆款的取舍
这篇解决什么问题:当你第一次听到”这个品类宽度不够””那个 SKU 深度太浅”时,可能觉得只是业务在讲”商品多不多”。本文将商品宽度与深度拆解为可理解的结构化概念,说清楚它为什么是供应链上游品类规划的第一道决策,以及长尾与爆款之争背后的业务逻辑。
一、先从一个”系统设计问题”说起假设你是一名研发,现在要设计一个电商商品库。你面临一个选择:
方案 A:商品库里有 100 个类目,每个类目下只有 3~5 个 SKU。
方案 B:商品库里有 10 个类目,每个类目下有 200~500 个 SKU。
这两个方案的表结构几乎一样,但业务含义完全不同。方案 A 是”广撒网”,什么都卖但每个品类都不精;方案 B 是”深挖井”,只做少数品类但每个都做到极致。
这个选择,就是商品宽度(Width) 与商品深度(Depth) 的取舍。它是零售企业在品类规划阶段要回答的第一个问题,也是决定后续采购、仓储、配送、补货所有环节复杂度的源头。
在深入定义之前,先把两个核心术语说清楚:
SKU(Stock Keeping Unit):库存量单位,是商品管理 ...
品类树与类目层级:一级/二级/三级/叶子类目如何设计
品类树与类目层级:一级/二级/三级/叶子类目如何设计
这篇解决什么问题:作为一个研发同学,你肯定熟悉树形结构。但当一个后端接口返回 categoryLevel: 3 时,这个“3”到底意味着什么业务含义?为什么有的平台商品挂在三级类目下,有的挂在叶子类目下?品类树不是随便长的,它的每一层都对应着一次业务决策权力的下放。这篇文章帮你把“树”从数据结构还原成业务语言。
一、为什么需要品类树:先回答“用户怎么找到货”想象一个没有品类树的电商平台。首页没有分类导航,搜索框也猜不出你想找什么,所有商品在一个大池子里随机展示。用户想买一包婴儿湿巾,平台却给他推荐了汽车轮胎。
品类树解决的第一个业务问题是可发现性:让用户在没有任何明确关键词的情况下,通过“逐层缩小范围”找到商品。这和操作系统里的文件目录是一个道理——你不会把几万个文件全堆在桌面,而是建一层层文件夹。
但零售的品类树比文件目录多了一层含义:它决定了商品在组织内部“归谁管”。一个“婴儿湿巾”挂在哪个类目下,决定了是母婴采购团队负责谈判供应商,还是清洁用品采购团队负责。类目划分不清,会出现两个团队同时对接同 ...
品类规划入门:什么是品类,零售电商为什么要做品类规划
品类规划入门:什么是品类,零售电商为什么要做品类规划
本文面向研发工程师,解决一个基础问题:零售电商里天天挂在嘴边的「品类」到底是什么?「品类规划」又在解决什么业务问题?读完你会理解品类树、类目层级、商品宽度与深度这些概念背后的业务逻辑,以及它们如何影响一家电商公司的商品组织和经营效率。
一、先从「为什么」说起:一个电商平台为什么需要品类规划想象你打开一个电商 App,首页有几十个入口,搜索框可以搜任何东西。如果平台上有 1000 万个 SKU(Stock Keeping Unit,最小库存单位,比如「农夫山泉 550ml×24 瓶整箱」就是一个 SKU),用户怎么找到想要的商品?运营怎么管理这些商品?采购怎么决定该引入哪些商品、淘汰哪些商品?
这些问题不是靠技术架构能回答的,它需要一个业务模型来组织和管理商品。这个模型就是品类规划。
品类规划的核心目的,可以归纳为三件事:
让用户找得到:通过合理的类目层级和导航结构,降低用户的搜索和浏览成本。
让运营管得住:把海量 SKU 按业务逻辑分组,每组有明确的责任人、策略和目标,而不是面对一锅粥。
让生意算得清:每个品类的销售额、毛利、周 ...
MySQL 8.0 直方图与统计信息优化实战:让优化器不再“猜错”执行计划
MySQL 8.0 直方图与统计信息优化实战:让优化器不再“猜错”执行计划从一个诡异的慢查询说起凌晨两点,告警群里弹出一条消息:线上某订单查询接口 P99 响应时间从 80ms 飙到了 4.2s。
我打开慢查询日志,定位到这样一条 SQL:
123456789101112-- 慢查询日志中的原始 SQLSELECT order_id, user_id, order_amount, status, created_atFROM ordersWHERE status = 'PENDING' AND order_amount BETWEEN 500 AND 2000ORDER BY created_at DESCLIMIT 50;
初步排查发现:status 列和 order_amount 列上都有索引,数据量约 600 万行。按常理,这种查询不该慢。用 EXPLAIN 一看,问题立刻浮出水面:
123456789101112EXPLAINSELECT order_id, user_id, order_amount, ...
MySQL 主从复制延迟排查与优化实战:基于 GTID 的读写分离一致性保障
MySQL 主从复制延迟排查与优化实战:基于 GTID 的读写分离一致性保障从一个“支付后订单不存在”说起某天下午,客服反馈有用户支付成功后,立即在“我的订单”页面查不到刚刚的订单。几分钟后再刷新,订单又出现了。后端同学排查日志:写请求落到了主库,读请求走了从库,但从库还没同步完这笔数据。这就是典型的主从复制延迟导致的读写分离不一致问题。
读写分离能极大提升读扩展能力,但主从延迟像一颗“定时炸弹”。本文结合一次真实的生产排查经历,系统梳理 GTID 机制下的延迟排查方法,并落地一套“延迟阈值切换 + 强制走主库 + 半同步复制”的读写分离一致性保障方案。
1. 主从复制原理与 GTID 机制回顾MySQL 默认异步复制:主库写入 binlog,从库通过 IO 线程拉取 binlog 写入 relay log,再通过 SQL 线程回放。从库回放速度低于主库写入速度时,就产生延迟。
传统基于位点的复制(MASTER_LOG_FILE + MASTER_LOG_POS)在主机切换或拓扑变更时容易错位。GTID(Global Transaction Identifier)为每个事务分配全局唯一 ...
Redis 缓存策略对比实战:Cache Aside、Read/Write Through 与 Write Behind 在 MySQL 高并发读场景下的选型与实现
Redis 缓存策略对比实战:Cache Aside、Read/Write Through 与 Write Behind 在 MySQL 高并发读场景下的选型与实现某电商商品详情接口 QPS 从 200 涨到 5000,MySQL 的 CPU 直接飙到 85%。加了一层 Redis 缓存后,接口响应从 120ms 降到 8ms,MySQL 负载降了 70%。但随之而来的是一个经典问题:缓存和数据库的一致性到底怎么保证?
这篇文章不讨论「缓存的 7 大经典问题」这种大而全的清单,而是聚焦三种缓存读写模式的真实代码实现和选型决策。每个模式我都会给出可直接运行的 Java 代码,并在最后说明它们各自的数据安全边界。
先看一张总览图:
12345678910111213141516┌─────────────────────────────────────────────────────────────────┐│ 三种缓存策略的核心差异 │├──────────────┬───────────── ...
Doris 冷热分层存储实战:基于对象存储的数据生命周期管理与查询性能权衡
Doris 冷热分层存储实战:基于对象存储的数据生命周期管理与查询性能权衡先说一个真实场景:我们有一张订单明细表,每天新增约 2000 万行,数据量以每月 6 亿行的速度增长。业务上,最近 7 天的订单查询非常频繁,需要毫秒级响应;90 天内的数据偶尔会做运营分析;更早的数据基本只有审计和合规需求,一年也查不了几次。如果所有数据都放在 SSD 上,存储成本高得离谱;全部放机械盘又会影响热数据查询。这种场景下,冷热分层几乎是必选项。
Doris 从 1.2 版本开始支持基于对象存储(S3/COS/OBS 等)的冷热分层。核心思路是:热数据留在本地 SSD/HDD,冷数据按照策略自动迁移到对象存储,查询时 Doris 可以透明地读取远程数据。本文基于 Doris 2.0.3 搭建一套完整的冷热分层实战环境,从存储策略配置、分区冷却、查询性能对比到数据保留策略,一步步带你落地。
1. 冷热分层的架构与原理先看一张架构图,直观理解 Doris 冷热分层的工作方式:
12345678+----------------+ +---------------- ...
MySQL InnoDB MVCC 原理与一致性读实战:从 undo log 多版本链到 ReadView 可见性判断
MySQL InnoDB MVCC 原理与一致性读实战:从 undo log 多版本链到 ReadView 可见性判断从一个”诡异”的读取现象说起先看一个在生产环境中经常让开发困惑的场景。
某天,同事跑来问我:”我在事务里更新了一行数据,还没提交,为什么另一个事务读到的还是旧值?是不是 MySQL 有缓存?”
这不是缓存问题,而是 MVCC(Multi-Version Concurrency Control,多版本并发控制) 在起作用。来看一个最小复现:
准备环境:MySQL 8.0,隔离级别为默认的 REPEATABLE READ。
12345678910111213141516-- 会话 ACREATE DATABASE IF NOT EXISTS mvcc_demo;USE mvcc_demo;CREATE TABLE account ( id INT PRIMARY KEY, balance INT NOT NULL, name VARCHAR(50) NOT NULL) ENGINE=InnoDB;INSERT INTO account VALUES (1, ...
后端工程师的下一个瓶颈:不是技术,而是思维模式
后端工程师的下一个瓶颈:不是技术,而是思维模式上周五晚上十一点,我盯着慢查询监控大盘发呆。一个跑了 3.2 秒的 SQL 被我连续优化了四轮——索引重建、子查询拆解、连表顺序调整、分区裁剪——执行时间降到了 0.8 秒。就在我准备合代码关电脑的时候,产品经理发来一条消息:“这个报表接口能不能再快一点?用户说打开要等两秒。”
我看着那行已优化的执行计划,突然意识到一个让人不舒服的事实:我把 SQL 调优到了物理层面的极限,但用户感受到的“慢”和我的“快”根本不在一张坐标图上。工具调优的熟练度越高,这种错位越明显。
当“会调”变成一种惯性过去一年我密集输出了不少 MySQL、Doris、Redis 的实战文章。从执行计划分析到 Buffer Pool 命中率,从 Doris 的物化视图到 Redis 的内存碎片治理,这些文章的阅读反馈都不错,也让我形成了一套固定的解题路径:遇到问题 → 定位瓶颈 → 调参数 / 改写法 / 加缓存 → 验证指标 → 沉淀文章。
这套路径本身没有问题,问题在于它太顺手了。顺手到我开始不自觉地用它解决所有问题——包括那些根本不该用调优来解决 ...
